使用MVVM在WPF中在视图之间动态切换

时间:2019-07-02 20:02:05

标签: c# wpf mvvm data-binding user-controls

我对WPF和MVVM模式还比较陌生。我正在尝试做的是让一个嵌套的用户控件根据MasterView中定义的DependencyProperty切换其视图。

我拥有的是一个UserControl,我们称其为LineItemsHolderView,其中包含使用ItemsContol填充的其他用户控件。

LineItemsHolderView用于填充另一个名为MainLineItemView的UserControl。

MainLineItemView的目的是根据MainLineItemView中定义的DependencyProperty将自身切换到LineItemView的特定类型。

LineItemView的两种类型是LineItemSummaryView和LineItemDetailView,它们各自具有自己的ViewModel。

在每个视图中,我将DataContext设置为构造函数中的相应ViewModel,并创建从视图DependencyProperties到ViewModels INotifyPropertyChanged属性的绑定。 (我将在下面提供代码示例)

在假设View / ViewModels已正确绑定和创建的前提下,我试图在MainLineItemView中使用ContentControl来显示基于DependencyPropery(在MainLineItemView中创建的名为SwitchView的整数)的正确视图。

但是,从LineItemsHolderView的ItemsControl DataTemplate设置此值时,它不会更新LineItemsHolderView中显示的MainLineItemView类型。

LineItemsHolderView.xaml

 <Grid>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*" />
                <RowDefinition Height="5*" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>

         <ScrollViewer Grid.Row="1">
                <ItemsControl ItemsSource="{Binding LineItems}">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <view:MainLineItemView SwitchView="1" Height="100" Padding="0,5,0,5" LineItem="{Binding RelativeSource={RelativeSource Self}}"/>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
        </ScrollViewer>
  </Grid>
</Grid>

LineItemsHolderView.xaml.cs

public partial class LineItemsHolderView : UserControl
    {
        public LineItemsHolderView()
        {
            InitializeComponent();
            DataContext = new LineItemsHolderViewModel();
        }
    }

LineItemsHolderViewModel.cs

internal class LineItemsHolderViewModel : INotifyPropertyChanged
    {
        public ObservableCollection<Models.LineItem> LineItems { get; set; }
        public LineItemsHolderViewModel ()
        {
            LineItems = new ObservableCollection<Models.LineItem>();
            for (int i = 0; i < 4; i++)
                LineItems.Add(new Models.LineItem(i));
        }


        #region INotifyPropertyChanged Members
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion
    }

MainLineItemView.xaml

<UserControl.Resources>
        <DataTemplate x:Key="SummaryView"  DataType="{x:Type vm:LineItemSummaryViewModel}">
            <local:LineItemSummaryView LineItem="{Binding LineItem}"/>
        </DataTemplate>
        <DataTemplate x:Key="DetailView" DataType="{x:Type vm:LineItemSummaryViewModel}">
            <local:LineItemDetailView LineItem="{Binding LineItem}"/>
        </DataTemplate>
    </UserControl.Resources>
    <Grid>
        <ContentControl Content="{Binding SelectedViewModel}">
            <ContentControl.Style>
                <Style TargetType="{x:Type ContentControl}">
                    <Setter Property="ContentTemplate" Value="{StaticResource SummaryView}" />
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding SwitchView, diag:PresentationTraceSources.TraceLevel=High}" Value="1">
                            <Setter Property="ContentTemplate" Value="{StaticResource DetailView}" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </ContentControl.Style>
        </ContentControl>
    </Grid>

MainLineItemView.xaml.cs

public partial class MainLineItemView : UserControl
    {
        public MainLineItemView()
        {
            InitializeComponent();

            this.DataContext = new MainLineItemViewModel();

            var bindingSwitchView = new Binding("SwitchView") { Mode = BindingMode.TwoWay };
            this.SetBinding(SwitchProperty, bindingSwitchView);

            var lineItemData = new Binding("LineItem") { Mode = BindingMode.TwoWay };
            this.SetBinding(LineItemProperty, lineItemData);
        }

        #region SwitchView DP
        public int SwitchView
        {
            get { return (int)GetValue(SwitchProperty); }
            set { SetValue(SwitchProperty, value); }
        }
        public static readonly DependencyProperty SwitchProperty = DependencyProperty.Register("SwitchView", typeof(int), typeof(MainLineItemView));
        #endregion

        #region LineItem DP
        public LineItem LineItem
        {
            get { return (LineItem)GetValue(LineItemProperty); }
            set { SetValue(LineItemProperty, value); }
        }
        public static readonly DependencyProperty LineItemProperty =
            DependencyProperty.Register("LineItem", typeof(LineItem),
              typeof(MainLineItemView));
        #endregion
    }

MainLineItemViewModel.cs

internal class MainLineItemViewModel : INotifyPropertyChanged
    {
        private int _currentView;
        public int CurrentView
        {
            get { return _currentView; }
            set
            {
                _currentView = value;
                OnPropertyChanged("CurrentView");
            }
        }
        private LineItem _lineItem;
        public LineItem LineItem
        {
            get { return _lineItem; }
            set
            {
                _lineItem= value;
                OnPropertyChanged("LineItem");
            }
        }

        public MainLineItemViewModel()
        {
        }

        #region INotifyPropertyChanged Members
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion
    }

如有必要,我可以提供LineItemSummaryView / LineItemSummaryViewModel和LineItemDetailView / LineItemDetailViewModel。

我希望在LineItemsHolderView.xaml中设置SwitchView =“ 1”时,应该在UI上显示LineItemDetailView。

由于我只是WPF的初学者,因此我可以对此进行任何改进,我们对此表示欢迎。

0 个答案:

没有答案