【问题标题】:ContentPresenter's Binding not updated when bound object is updated更新绑定对象时,ContentPresenter 的绑定未更新
【发布时间】:2012-08-15 16:22:40
【问题描述】:

我有一个主视图和两个子视图。单击 SubViewA 上的按钮时,我想从 SubViewA 切换到 SubViewB。 masterview 包含一个 contentpresenter,它绑定到 View,并在加载时初始化为 SubViewB。单击 SubViewA 上的按钮时,将调用 SubViewB 构造函数,但从未加载控件。我错过了什么?我也尝试过设置内容模板:

<ContentPresenter x:Name="contentPresenter" Content="{Binding View, PresentationTraceSources.TraceLevel=High}" />

这也不起作用。

主窗口:

<Window x:Class="WpfApplication2.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525"
    xmlns:local="clr-namespace:WpfApplication2">

<Grid>

    <TextBlock Text="MasterViewPage" />

    <ContentControl x:Name="content" Content="{Binding View}">
        <ContentControl.Resources>
            <DataTemplate DataType="{x:Type local:SubViewModelA}">
                <local:SubViewA></local:SubViewA>
            </DataTemplate>
            <DataTemplate DataType="{x:Type local:SubViewModelB}">
                <local:SubViewB></local:SubViewB>
            </DataTemplate>
        </ContentControl.Resources>
    </ContentControl>

</Grid>
</Window>

public partial class MainWindow
{
    public MainWindow()
    {
        Loaded += MainWindow_Loaded;
        InitializeComponent();
    }

    private void MainWindow_Loaded(object sender, System.Windows.RoutedEventArgs e)
    {
        DataContext = new MainViewModel();
    }      
}

子视图A:

<UserControl x:Class="WpfApplication2.SubViewA"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">

<Grid Margin="0,40,0,0">
    <TextBlock Text="Subview A" />

    <Button Height="50" Width="120" Content="Open View B" Command="{Binding OpenViewCommand}" />
</Grid>
</UserControl>

public partial class SubViewA
{
    public SubViewA()
    {
        Loaded += SubViewA_Loaded;
        InitializeComponent();
    }

    private void SubViewA_Loaded(object sender, System.Windows.RoutedEventArgs e)
    {
        DataContext = new SubViewModelA();
    }
}

视图模型:

public class MainViewModel : NotifyPropertyChanged
{
    private object _view;

    public object View
    {
        get { return _view; }
        set
        {
            _view = value;
            RaisePropertyChanged(() => View);
        }
    }

    public MainViewModel()
    {
        View = new SubViewA();
    }
}

public class SubViewModelA : MainViewModel
{
    public ICommand OpenViewCommand
    {
        get { return new DelegatingCommand(OpenView); }
    }

    private void OpenView()
    {
        View = new SubViewB();
    }
}

public class SubViewModelB : MainViewModel
{
}

提前致谢。

【问题讨论】:

    标签: wpf user-controls


    【解决方案1】:

    视图模型不应该包含对视图的引用,而是有一个属性ViewMode,它可以是一个enum,并在此触发here is an example(你可以设置ContentTemplate而不是Content为好)。

    【讨论】:

      【解决方案2】:

      好的,对我有用的解决方案是:

      MainView.xaml:

          <ContentControl x:Name="content">
              <ContentControl.Style>
                  <Style TargetType="{x:Type ContentControl}">
                      <Style.Triggers>
                          <DataTrigger Binding="{Binding View, PresentationTraceSources.TraceLevel=High}" Value="SubViewA">
                                  <Setter Property="ContentTemplate">
                                  <Setter.Value>
                                          <DataTemplate>
                                              <local:SubViewA />
                                          </DataTemplate>
                                  </Setter.Value>
                              </Setter>
                          </DataTrigger>
                          <DataTrigger Binding="{Binding View, PresentationTraceSources.TraceLevel=High}" Value="SubViewB">
                                  <Setter Property="ContentTemplate">
                                  <Setter.Value>
                                          <DataTemplate>
                                              <local:SubViewB />
                                          </DataTemplate>
                                      </Setter.Value>
                              </Setter>
                          </DataTrigger>
                      </Style.Triggers>
                  </Style>
              </ContentControl.Style>
          </ContentControl>
      

      在 SubViewA.xaml 中:

      <Button Height="50" Width="120" Content="Open View B" Command="{Binding Path=DataContext.OpenViewCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}, PresentationTraceSources.TraceLevel=High}" />
      

      原因是 View 没有设置在 MainViewModel 上,而是设置在子视图上(继承自 MainViewModel)。当删除继承以实际设置 MainViewModel 上的视图时,一切正常。

      【讨论】:

        【解决方案3】:

        我同意直接在模型中设置视图是不好的。但无论如何,我尝试了您的解决方案(两者)并且 SubViewB 仍未加载。构造函数被调用,但从未调用SubViewB_Loaded。因此,结果是 SubViewB 永远不会显示。

        datacontextchanged 永远不会在 contentcontrol 上触发。所以,我仍然缺少一些东西。

        主视图:

        <Window x:Class="WpfApplication2.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525"
            xmlns:local="clr-namespace:WpfApplication2">
        
        <Grid>
        
            <TextBlock Text="MasterViewPage" />
        
            <ContentControl x:Name="content">
                <ContentControl.Style>
                    <Style TargetType="{x:Type ContentControl}">
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding View}" Value="SubViewA">
                                <Setter Property="Content">
                                    <Setter.Value>
                                        <local:SubViewA />
                                    </Setter.Value>
                                </Setter>
                            </DataTrigger>
                            <DataTrigger Binding="{Binding View}" Value="SubViewB">
                                <Setter Property="Content">
                                    <Setter.Value>
                                        <local:SubViewB />
                                    </Setter.Value>
                                </Setter>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </ContentControl.Style>
            </ContentControl>
        </Grid>
        </Window>
        

        在视图模型中:

        public class MainViewModel : NotifyPropertyChanged
        {
            private string _view;
        
            public string View
            {
                get { return _view; }
                set
                {
                    _view = value;
                    RaisePropertyChanged(() => View);
                }
            }
        
            public MainViewModel()
            {
                View = "SubViewA";
            }
        }
        
        public class SubViewModelA : MainViewModel
        {
            public ICommand OpenViewCommand { get { return new DelegatingCommand(OpenView); } }
        
            private void OpenView()
            {
                View = "SubViewB";
            }
        }
        
        public class SubViewModelB : MainViewModel
        {
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-08-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-06
          • 1970-01-01
          相关资源
          最近更新 更多