如何通过仅单击用户控件中的一个按钮来更新框架的 Source 属性?

发布于 2024-11-09 18:14:49 字数 693 浏览 3 评论 0原文

我想了解如何通过根据点击计数仅单击一个“下一步”按钮来更新源属性,并能够在每次单击该按钮时将不同的页面加载到框架中。任何建议都将受到高度赞赏!先感谢您。

主窗口代码:

<Grid x:Name="LayoutRoot">
    <Frame Content="Frame" Source="/WpfApplication1;component/Page1.xaml"/>
    <local:NavUserControl HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
</Grid>

包含按钮的用户控件:

<StackPanel x:Name="LayoutRoot" Orientation="Horizontal" VerticalAlignment="Bottom" HorizontalAlignment="Center" Margin="0,0,0,20">
    <Button Content="Back" HorizontalAlignment="Left" Width="75"/>
    <Button Content="Next" HorizontalAlignment="Left" Width="75" />
</StackPanel>

I’d like to find out about how to update a source property by clicking only one "Next" button based on a click count and being able to load different pages into frame each time the button is clicked another time. Any advice is highly appreciated! Thank you in advance.

Main Window Code:

<Grid x:Name="LayoutRoot">
    <Frame Content="Frame" Source="/WpfApplication1;component/Page1.xaml"/>
    <local:NavUserControl HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
</Grid>

User control that contains the button:

<StackPanel x:Name="LayoutRoot" Orientation="Horizontal" VerticalAlignment="Bottom" HorizontalAlignment="Center" Margin="0,0,0,20">
    <Button Content="Back" HorizontalAlignment="Left" Width="75"/>
    <Button Content="Next" HorizontalAlignment="Left" Width="75" />
</StackPanel>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

听风念你 2024-11-16 18:14:49

创建一个实现 NextPageCommandPreviousPageCommand 命令的 PageViewModel 类,这些命令分别引发 UserNavieratedToNextPageUserNavieratedToPreviousPage 事件。为了简单起见,还让它们公开 PageViewModel 类型的 NextPagePreviousPage 属性。为每个页面创建 PageViewModel 的子类。

为拥有的 UserControl 创建一个视图模型类,该类公开 PageViewModel 类型的 CurrentPage 属性。创建所有 PageViewModel 对象,并在每个对象上设置 NextPagePreviousPage。在这些对象上添加导航事件的处理程序,如下所示:

public void Page_UserNavigatedToNextPage(object sender, EventArgs e)
{
   if (sender == CurrentPage && CurrentPage.NextPage != null)
   {
      CurrentPage = CurrentPage.NextPage;
   }
}

假设您已经实现了属性更改通知,现在每当当前页面的 NextPageCommandPreviousPageCommand 执行时, CurrentPage 属性将更新并反映在 UI 中。如果您已经为每种页面视图模型类型创建了数据模板,那么您所需要的一切都

<ContentPresenter Content="{Binding CurrentPage}"/>

在您的用户控件中,您就可以开始了。

如果“下一个”/“上一个”按钮在您的控件中,而不是在页面中,则在主视图模型中实现公开 CurrentPage.NextPageCommandCurrentPage.PreviousPageCommand 的属性,并且将按钮绑定到它们。

Create a PageViewModel class that implements NextPageCommand and PreviousPageCommand commands, which raise (respectively) UserNavigatedToNextPage and UserNavigatedToPreviousPage events. To make it simple, also have them expose NextPage and PreviousPage properties of type PageViewModel. Create subclasses of PageViewModel for each page.

Create a view model class for the owning UserControl that exposes a CurrentPage property of type PageViewModel. Create all of the PageViewModel objects and set NextPage and PreviousPage on each. Add handlers for the navigation events on these object that look something like:

public void Page_UserNavigatedToNextPage(object sender, EventArgs e)
{
   if (sender == CurrentPage && CurrentPage.NextPage != null)
   {
      CurrentPage = CurrentPage.NextPage;
   }
}

Assuming that you've implemented property-change notification, now whenever the current page's NextPageCommand or PreviousPageCommand executes, the CurrentPage property will be updated and will be reflected in the UI. If you've created a data template for each page view model type, all you need is

<ContentPresenter Content="{Binding CurrentPage}"/>

in your user control and you're good to go.

If the Next/Previous buttons are in your control, and not in the page, then implement properties in the main view model that expose CurrentPage.NextPageCommand and CurrentPage.PreviousPageCommand, and bind the buttons to them.

兰花执着 2024-11-16 18:14:49

在您的 NavUserControl 中,我将为下一个和后退按钮连接事件或命令(或两者)。然后,您可以从 MainWindow 内访问这些内容,并将适当的值设置到 Source 属性中。

如果您选择事件路线,请附加到事件并直接设置源。

如果您采用命令路线,请在视图模型中设置一个命令,将其绑定到用户控件,并将 Source 属性绑定到视图模型中的另一个值。

编辑:根据OP的请求添加一些代码。请记住,这并不是最佳实践。只是一些例子。

活动路线应该是最简单的。我想你已经知道如何做到这一点了。只需添加:

public event EventHandler BackClicked;
public event EventHandler NextClicked;

private void Back_Click(object sender, RoutedEventArgs e)
{
    BackClicked(sender, e);
}

private void Next_Click(object sender, RoutedEventArgs e)
{
    NextClicked(sender, e);
}

事件到您的 NavUserControl。然后将您的 XAML 更改为:

<StackPanel x:Name="LayoutRoot" Orientation="Horizontal" VerticalAlignment="Bottom" HorizontalAlignment="Center" Margin="0,0,0,20">    
    <Button Content="Back" HorizontalAlignment="Left" Width="75" Click="Back_Click" />    
    <Button Content="Next" HorizontalAlignment="Left" Width="75" Click="Next_Click" />
</StackPanel>

现在在 MainWindow.xaml.cs 文件中添加:

private void BackClicked(object sender, EventArgs e)
{
    Uri source = // Whatever your business logic is to determine the previous page;
    _Frame.Source = source;
}

private void NextClicked(object sender, EventArgs e)
{
    Uri source = // Whatever your business logic is to determine the next page;
    _Frame.Source = source;
}

并将 MainWindow XAML 更改为:

<Grid x:Name="LayoutRoot">
    <Frame x:Name="_Frame" Content="Frame" 
           Source="/WpfApplication1;component/Page1.xaml"/>
    <local:NavUserControl HorizontalAlignment="Center" VerticalAlignment="Bottom" 
                          BackClicked="BackClicked" NextClicked="NextClicked" />
</Grid>

使用命令路径需要更多的架构设计,但更干净。我建议使用您最喜欢的 MVVM 工具包。我最喜欢的是 MVVMLight,因此我将在本示例中使用它。

创建一个 ViewModel 类,如下所示:

public class ViewModel : GalaSoft.MvvmLight.ViewModelBase
{
    private Uri _Source;
    public Uri Source
    {
        get { return _Source; }
        set
        {
            if (_Source != value)
            {
                _Source = value;
                RaisePropertyChanged("Source");
            }
        }
    }



    private GalaSoft.MvvmLight.Command.RelayCommand _BackCommand;
    public ICommand BackCommand
    {
        get
        {
            if (_BackCommand == null)
            {
                _BackCommand = new GalaSoft.MvvmLight.Command.RelayCommand(() =>
                {
                    Uri source = // Whatever your business logic is to determine the previous page
                    Source = source;
                });
            }
            return _BackCommand;
        }
    }

    private GalaSoft.MvvmLight.Command.RelayCommand _NextCommand;
    public ICommand NextCommand
    {
        get
        {
            if (_NextCommand == null)
            {
                _NextCommand = new GalaSoft.MvvmLight.Command.RelayCommand(() =>
                {
                    Uri source = // Whatever your business logic is to determine the next page
                    Source = source;
                });
            }
            return _NextCommand;
        }
    }
}

在 MainWindow.xaml.cs 中,创建此类的实例并将 DataContext 属性设置为该实例。然后设置您的绑定:

<Grid x:Name="LayoutRoot">    
    <Frame Content="Frame" Source="{Binding Source}"/>    
    <local:NavUserControl HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
</Grid>

并且

<StackPanel x:Name="LayoutRoot" Orientation="Horizontal" VerticalAlignment="Bottom" HorizontalAlignment="Center" Margin="0,0,0,20">    
    <Button Content="Back" HorizontalAlignment="Left" Width="75" Command="{Binding BackCommand}"/>    
    <Button Content="Next" HorizontalAlignment="Left" Width="75" Command="{Binding NextCommand}" />
</StackPanel>

绑定示例是非常简单的 MVVM 风格的 WPF。我建议您走这条路,如果您需要更多帮助,请阅读 WPF 中的 MVVM。有大量教程和书籍形式的资源。 在这里搜索 SO 也有很大帮助。

再次编辑:

将构造函数更改为:

public MainWindow()
{
    this.InitializeComponent();

    // Insert code required on object creation below this point.
    DataContext = new ViewModel();
}

In your NavUserControl, I would wire up either events or commands (or both, perhaps) for the next and back buttons. Then you can access those from within the MainWindow and set the appropriate value into the Source property.

If you go the event route, attach onto the events and set the Source directly.

If you go the command route, setup a command in your viewmodel, bind it to the usercontrol, and bind the Source property to another value in your viewmodel.

Edit: Adding some code per the OP's request. Keep in mind, this is not intended to be best practices. Just some examples.

To go the event route should be the simplest. You already know how to do this, I'd imagine. Just add:

public event EventHandler BackClicked;
public event EventHandler NextClicked;

private void Back_Click(object sender, RoutedEventArgs e)
{
    BackClicked(sender, e);
}

private void Next_Click(object sender, RoutedEventArgs e)
{
    NextClicked(sender, e);
}

events to your NavUserControl. Then change your XAML to:

<StackPanel x:Name="LayoutRoot" Orientation="Horizontal" VerticalAlignment="Bottom" HorizontalAlignment="Center" Margin="0,0,0,20">    
    <Button Content="Back" HorizontalAlignment="Left" Width="75" Click="Back_Click" />    
    <Button Content="Next" HorizontalAlignment="Left" Width="75" Click="Next_Click" />
</StackPanel>

And now in your MainWindow.xaml.cs file, add:

private void BackClicked(object sender, EventArgs e)
{
    Uri source = // Whatever your business logic is to determine the previous page;
    _Frame.Source = source;
}

private void NextClicked(object sender, EventArgs e)
{
    Uri source = // Whatever your business logic is to determine the next page;
    _Frame.Source = source;
}

and change the MainWindow XAML to be:

<Grid x:Name="LayoutRoot">
    <Frame x:Name="_Frame" Content="Frame" 
           Source="/WpfApplication1;component/Page1.xaml"/>
    <local:NavUserControl HorizontalAlignment="Center" VerticalAlignment="Bottom" 
                          BackClicked="BackClicked" NextClicked="NextClicked" />
</Grid>

Going the command route takes a little more architecting, but is a lot more clean. I'd recommend using your favorite MVVM toolkit. My favorite is MVVMLight, so that's what I'll use for this example.

Create a ViewModel class, something like this:

public class ViewModel : GalaSoft.MvvmLight.ViewModelBase
{
    private Uri _Source;
    public Uri Source
    {
        get { return _Source; }
        set
        {
            if (_Source != value)
            {
                _Source = value;
                RaisePropertyChanged("Source");
            }
        }
    }



    private GalaSoft.MvvmLight.Command.RelayCommand _BackCommand;
    public ICommand BackCommand
    {
        get
        {
            if (_BackCommand == null)
            {
                _BackCommand = new GalaSoft.MvvmLight.Command.RelayCommand(() =>
                {
                    Uri source = // Whatever your business logic is to determine the previous page
                    Source = source;
                });
            }
            return _BackCommand;
        }
    }

    private GalaSoft.MvvmLight.Command.RelayCommand _NextCommand;
    public ICommand NextCommand
    {
        get
        {
            if (_NextCommand == null)
            {
                _NextCommand = new GalaSoft.MvvmLight.Command.RelayCommand(() =>
                {
                    Uri source = // Whatever your business logic is to determine the next page
                    Source = source;
                });
            }
            return _NextCommand;
        }
    }
}

In your MainWindow.xaml.cs, create an instance of this class and set your DataContext property to that instance. Then setup your bindings:

<Grid x:Name="LayoutRoot">    
    <Frame Content="Frame" Source="{Binding Source}"/>    
    <local:NavUserControl HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
</Grid>

and

<StackPanel x:Name="LayoutRoot" Orientation="Horizontal" VerticalAlignment="Bottom" HorizontalAlignment="Center" Margin="0,0,0,20">    
    <Button Content="Back" HorizontalAlignment="Left" Width="75" Command="{Binding BackCommand}"/>    
    <Button Content="Next" HorizontalAlignment="Left" Width="75" Command="{Binding NextCommand}" />
</StackPanel>

The binding example is pretty straight-forward MVVM-style WPF. I'd suggest you go that route and if you need more help, go read up on MVVM in WPF. Lots of resources out there in the form of tutorials and books. Searching here on SO can help a lot as well.

Edit again:

Change your constructor to this:

public MainWindow()
{
    this.InitializeComponent();

    // Insert code required on object creation below this point.
    DataContext = new ViewModel();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文