WPF中的问题 - MVVM - 在UserControl中按下按钮时ViewNavigation无法正常工作

时间:2018-02-19 12:54:18

标签: wpf mvvm

我是WPF MVVM的新手。我有 MainWindow.xaml 这里Grid分为两列。 Column1与 MenuUserControl.xaml 挂钩,其中有两个名为 Page1 Page2 的按钮。 Column2与ContentControl挂钩,用于根据 MenuUserControl.xaml 中的按钮单击显示视图。单击按钮时查看导航无效。请给我一个有效的解决方案。

我有 MainWindowViewModel.cs 的ViewModel和 MenuuserControlViewModel.cs Page1UserControlViewModel Page2UserControlViewModel MainWindowViewModel 包含名为SelectedViewModel的属性,该属性与ContentControl绑定

<ContentControl x:Name="Pages" Content="{Binding SelectedViewModel}"/>

MainWindow.Xaml

<Window x:Class="WpfNavigationViewTestApplication.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"       
        xmlns:local="clr-namespace:WpfNavigationViewTestApplication.Views"
        xmlns:viewModel="clr-namespace:WpfNavigationViewTestApplication.ViewModel"
        mc:Ignorable="d"
        Title="Master Part List" Width="1250" Height="700" ResizeMode="NoResize" WindowStartupLocation="CenterScreen">


    <Window.DataContext>
        <viewModel:MainWindowViewModel/>
    </Window.DataContext>


    <Window.Resources>


        <DataTemplate DataType="{x:Type viewModel:Page1ViewModel}">
            <local: Page1UserControlView/>
        </DataTemplate>

        <DataTemplate DataType="{x:Type viewModel:Page2ViewModel}">
            <local: Page2UserControlView/>
        </DataTemplate>

    </Window.Resources>

    <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="125" />
                <RowDefinition Height="*" />
                <RowDefinition Height="50" />
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="160"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <GridSplitter  Grid.Row="1" Grid.ColumnSpan="0" HorizontalAlignment="Stretch" VerticalAlignment="Top" Height="10" Background="Gray"  ShowsPreview="True" IsEnabled="False" />     

              <Grid Name="MenuGrid" Grid.Row="1" Grid.Column="0" Margin="3,13,3,3">
                <local:MplMenuView DataContext="{Binding Path= MplMenuViewModel}" />
            </Grid> 

            <Grid Name="PageGrid" Grid.Row="1" Grid.Column="1" Margin="13,13,3,3">               
                <ContentControl x:Name="Pages" Content="{Binding SelectedViewModel}"/>
            </Grid>
            </Grid>

        </Grid>
    </ScrollViewer>
</Window>

MainWindowViewModel.cs

public class MainWindowViewModel: INotifyPropertyChanged
    {
        private BaseViewModel selectedViewModel;
        public BaseViewModel SelectedViewModel
        {
            get { return selectedViewModel; }
            set
            {
                selectedViewModel = value;
                OnPropertyChanged("SelectedViewModel");
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propName));
            }
        }
     }

MenuUserControl.Xaml

<UserControl x:Class="WpfNavigationViewTestApplication.Views. MenuUserControl"
             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" 
             xmlns:local="clr-namespace:WpfNavigationViewTestApplication.Views"
             xmlns:viewModel="clr-namespace:WpfNavigationViewTestApplication.ViewModel"
             mc:Ignorable="d" 
             Height="460" Width="154">

    <UserControl.Resources>
        <Style x:Key="menuButton" TargetType="Button">
            <Setter Property="Height" Value="25"/>
            <Setter Property="Width" Value="130"/>
            <Setter Property="Margin" Value="0,4,0,0"/>
            <Setter Property="HorizontalAlignment" Value="Center"/>
            <Setter Property="VerticalAlignment" Value="Center"/>
            <Setter Property="FontFamily" Value="Arial"/>
            <Setter Property="FontSize" Value="12"/>
        </Style>
        <BooleanToVisibilityConverter x:Key="BoolToVis" />

    </UserControl.Resources>

    <UserControl.DataContext>
        <viewModel:MenuUserControlViewModel/>
    </UserControl.DataContext>

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

        <StackPanel Grid.Row="0" Orientation="Vertical">
            <Grid >
                <Grid.RowDefinitions>
                    <RowDefinition Height="*"/>
                    <RowDefinition Height="105"/>
                    <RowDefinition Height="90" />
                </Grid.RowDefinitions>
                <StackPanel Grid.Row="0" Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center" >
                    <Button Style="{StaticResource menuButton}" Content="Page1" Command="{Binding Page1Command}"  />
                    <Button Style="{StaticResource menuButton}" Content="Page2" Command="{Binding Page2Command}"/>                    
                </StackPanel>
                <StackPanel Grid.Row="1" Orientation="Vertical" />
                <StackPanel Grid.Row="2" Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center" >                    
                </StackPanel>
            </Grid>
        </StackPanel>
        <StackPanel Grid.Row="1" Orientation="Vertical"  >            
        </StackPanel>
    </Grid>
</UserControl>

MenuUserControlViewModel.cs

public class MenuUserControlViewModel : MainWindowViewModel
    {
        public ICommand Page1Command { get; set; }
        public ICommand Page2Command { get; set; }

        public MenuUserControlViewModel ()
        {
            Page1Command = new BaseCommand(OpenPage1View);
            Page2Command = new BaseCommand(OpenPage2View);
        }
        private void OpenPage1View (object obj)
        {
            SelectedViewModel = new Page1UserControlViewModel ();
        }
        private void OpenPage2View (object obj)
        {
            SelectedViewModel = new Page2UserControlViewModel ();
        }
    }

BaseCommand.cs

public class BaseCommand : ICommand
    {
        private Predicate<object> _canExecute;
        private Action<object> _method;
        public event EventHandler CanExecuteChanged;

        public BaseCommand(Action<object> method)
            : this(method, null)
        {
        }

        public BaseCommand(Action<object> method, Predicate<object> canExecute)
        {
            _method = method;
            _canExecute = canExecute;
        }

        public bool CanExecute(object parameter)
        {
            if (_canExecute == null)
            {
                return true;
            }

            return _canExecute(parameter);
        }

        public void Execute(object parameter)
        {
            _method.Invoke(parameter);
        }
    }

1 个答案:

答案 0 :(得分:0)

您正在设置另一个SelectedViewModel实例的MainWindowViewModel属性。 MenuUserControlViewModel不应继承MainWindowViewModel。它应该与现有的通信。

MenuUserControl.xaml

中删除此内容
<UserControl.DataContext>
    <viewModel:MenuUserControlViewModel/>
</UserControl.DataContext>

...并在MenuUserControlViewModel

中创建MainWindowViewModel的实例
public class MainWindowViewModel : INotifyPropertyChanged
{
    private BaseViewModel selectedViewModel;
    public BaseViewModel SelectedViewModel
    {
        get { return selectedViewModel; }
        set
        {
            selectedViewModel = value;
            OnPropertyChanged("SelectedViewModel");
        }
    }

    public MainWindowViewModel()
    {
        MplMenuViewModel = new MenuUserControlViewModel(this);
    }

    public MenuUserControlViewModel MplMenuViewModel { get; private set; }

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }
    }
}

public class MenuUserControlViewModel : MainWindowViewModel
{
    private readonly MainWindowViewModel _mainWindowViewModel;

    public ICommand Page1Command { get; set; }
    public ICommand Page2Command { get; set; }

    public MenuUserControlViewModel(MainWindowViewModel mainWindowViewModel)
    {
        _mainWindowViewModel = mainWindowViewModel;
        Page1Command = new BaseCommand(OpenPage1View);
        Page2Command = new BaseCommand(OpenPage2View);
    }
    private void OpenPage1View(object obj)
    {
        _mainWindowViewModel.SelectedViewModel = new Page1UserControlViewModel();
    }
    private void OpenPage2View(object obj)
    {
        _mainWindowViewModel.SelectedViewModel = new Page2UserControlViewModel();
    }
}

<强> MainWindow.xaml:

<local:MplMenuView DataContext="{Binding Path=MplMenuViewModel}" />