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

时间:2011-05-24 16:14:44

标签: wpf binding frame

我想知道如何通过单击一个“下一步”按钮来更新源属性,该按钮基于点击次数,并且每次再次单击该按钮时能够将不同的页面加载到帧中。任何建议都非常感谢!提前谢谢。

主窗口代码:

<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>

2 个答案:

答案 0 :(得分:2)

创建一个实现PageViewModelNextPageCommand命令的PreviousPageCommand类,它们分别引发UserNavigatedToNextPageUserNavigatedToPreviousPage个事件。为简化起见,还要让它们公开NextPage类型的PreviousPagePageViewModel属性。为每个页面创建PageViewModel的子类。

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

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

假设您已实施了属性更改通知,现在只要当前页面的NextPageCommandPreviousPageCommand执行,CurrentPage属性就会更新,并会反映在用户界面中。如果您为每个页面视图模型类型创建了数据模板,则只需

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

在你的用户控件中,你很高兴。

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

答案 1 :(得分:1)

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

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

如果您执行命令路由,请在viewmodel中设置命令,将其绑定到usercontrol,并将Source属性绑定到viewmodel中的另一个值。

编辑:根据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。以教程和书籍的形式提供了大量资源。 Searching here on SO也可以提供很多帮助。

再次修改:

将构造函数更改为:

public MainWindow()
{
    this.InitializeComponent();

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