c# - 在用户控件内单击按钮更改 View

标签 c# wpf xaml mvvm

我在一个窗口中有一个两行网格。在第一行有一个带有按钮的堆栈面板。单击一个按钮会在网格的第二行显示一个用户控件。(我得到了该部分的工作)。现在在用户控件内部有多个按钮应该更改网格第二行的内容(将当前用户控件更改为另一个)。
当我单击客户用户控件中的按钮并将断点放置到 BaseViewModel 中的 NavigationCommand 时,它实际上会更改 CurrentViewModel 但不会出现在实际窗口中。

MainWindow.xaml

<Window x:Class="TestProject.View.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:viewmodel="clr-namespace:TestProject.ViewModel"
        xmlns:local="clr-namespace:TestProject"
        xmlns:view="clr-namespace:TestProject.View"
        mc:Ignorable="d"
        Title="MainWindow" Width="966" Height="897">
    <Window.DataContext>
        <viewmodel:MainWindowViewModel/>
    </Window.DataContext>
<Grid >
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"></RowDefinition>
        <RowDefinition Height="*"></RowDefinition>
    </Grid.RowDefinitions>
    <!--Верхнее меню -->
    <Grid Grid.Row="0">
        <StackPanel HorizontalAlignment="Left" Orientation="Horizontal" >
            <Button x:Name="Visits" Background="Transparent" Command="{Binding NavigationCommand}" CommandParameter="visits"  BorderThickness="0" Width="Auto"  Height="Auto" Margin="8,0,0,0">        
                    <Image Source="../icon/document-changed.png" Width="16" Height="16"/>
            </Button>
            <Button x:Name="Patients" Background="Transparent" Command="{Binding NavigationCommand}" CommandParameter="patients"  BorderThickness="0" Width="Auto"  Height="Auto" Margin="8,0,0,0">
                    <Image Source="../icon/document-changed.png" Width="16" Height="16"/>
            </Button>
            <Button x:Name="Customers" Background="Transparent" Command="{Binding NavigationCommand}" CommandParameter="customers"  BorderThickness="0" Width="Auto"  Height="Auto" Margin="8,0,0,0">
                    <Image Source="../icon/user.png" Width="16" Height="16"/>
            </Button>
            <Button x:Name="Goods" Background="Transparent" Command="{Binding NavigationCommand}" CommandParameter="customer"  BorderThickness="0" Width="Auto"  Height="Auto" Margin="8,0,0,0">
                    <Image Source="../icon/folder_documents.png" Width="16" Height="16"/>
            </Button>
            <Button x:Name="Services" Background="Transparent" Command="{Binding NavigationCommand}" CommandParameter="services" BorderThickness="0" Width="Auto"  Height="Auto" Margin="8,0,0,0">
                    <Image Source="../icon/folder_documents.png" Width="16" Height="16"/>
            </Button>                
        </StackPanel>
    </Grid>
    <ContentControl x:Name="Content" Grid.Row="1" Content="{Binding CurrentViewModel}"></ContentControl>
    </Grid>
</Window>

BaseViewModel
namespace TestProject.ViewModel
{
    public class BaseViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged = delegate { };
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        public DelegateCommand<string> NavigationCommand { get; set; }        
        public BaseViewModel()
        {        
            NavigationCommand = new DelegateCommand<string>(OnNavigate);            
        }

        private void OnNavigate(string navPath)
        {
            switch (navPath)
            {
                case "customers":
                    CurrentViewModel = new CustomersViewModel();                    
                    break;
                case "visits":
                    CurrentViewModel = new VisitsViewModel();                    
                    break;
                case "patients":
                    CurrentViewModel = new PatientsViewModel();                    
                    break;
                case "customer":                    
                    CurrentViewModel = new CustomerViewModel();
                    break;
                case "visit":                    
                    CurrentViewModel = new VisitViewModel();
                    break;
            }
        }

        private object _currentViewModel;

        public object CurrentViewModel
        {
            get { return _currentViewModel; }
            set
            {
                if (_currentViewModel != value)
                {
                    _currentViewModel = value;
                    OnPropertyChanged();
                }
            }
        }
        private object _currentText;

        public object CurrentText
        {
            get { return _currentText; }
            set
            {
                if (_currentText != value)
                {
                    _currentText = value;
                    OnPropertyChanged();
                }
            }
        }
    }
}

客户.xaml
<UserControl x:Class="TestProject.View.Customers"
             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:TestProject.View"
             xmlns:viewModel="clr-namespace:TestProject.ViewModel"
             mc:Ignorable="d"       
             >
    <UserControl.DataContext>
        <viewModel:CustomersViewModel/>
        </UserControl.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="25"></RowDefinition>
            <RowDefinition Height="50"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>
        <Label Grid.Row="0" Background="#FFF3EB96">Клиенты</Label>
        <StackPanel Grid.Row="1" Orientation="Horizontal">
            <Button Command="{Binding NavigationCommand}" CommandParameter="customer"  Background="Transparent"  BorderThickness="0" Width="Auto"  Height="Auto" Margin="8,0,0,0">
                <StackPanel Orientation="Horizontal">
                    <Image Source="../icon/plus_32.png" Width="32" Height="32"/>
                </StackPanel>
            </Button>

        </StackPanel>
    </Grid>
</UserControl>

最佳答案

您似乎已经定义了 CurrentViewModel所有 View 模型的公共(public)基类中的属性。这是错误的。
ContentControl在 View 中绑定(bind)到 View 模型类的特定实例,因此设置 CurrentViewModel CustomersViewModel 的属性(property)不会影响 ContentControl绑定(bind)到 CurrentViewModel MainWindowViewModel 的属性(property).
CustomersViewModel应该直接引用 MainWindowViewModel ,否则您将不得不使用某种信使/事件聚合器或共享服务在它们之间进行通信:https://blog.magnusmontin.net/2014/02/28/using-the-event-aggregator-pattern-to-communicate-between-view-models/ .

如果您通过引用 MainWindowViewModel 注入(inject) subview 模型创建它们时,您可以使用此引用进行导航:

主窗口 View 模型:

public class MainWindowViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged = delegate { };
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    public DelegateCommand<string> NavigationCommand { get; set; }
    public BaseViewModel()
    {
        NavigationCommand = new DelegateCommand<string>(OnNavigate);
    }

    private void OnNavigate(string navPath)
    {
        switch (navPath)
        {
            case "customers":
                CurrentViewModel = new CustomersViewModel(this);
                break;
            ...
        }
    }

客户查看型号:
public class CustomersViewModel
{
    private readonly MainWindowViewModel _vm;
    public CustomersViewModel(MainWindowViewModel vm)
    {
        _vm = vm;
        NavigationCommand = new DelegateCommand<string>(OnNavigate);
    }

    public DelegateCommand<string> NavigationCommand { get; set; }


    private void OnNavigate(string navPath)
    {
        _vm.CurrentViewModel = new SomeOtherViewModel();
    }
}

关于c# - 在用户控件内单击按钮更改 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45140890/

相关文章:

C# 试图解密文件以仅处理内存

c# - 使用 ReactiveObject 执行任何操作时出现 ReactiveUI 5.1 stackoverflowexception

WPF 文本框 VerticalContentAlignment 不工作

c# - 如何在 WPF/MVVM 中对绑定(bind)到相同实例的两个 ListView 进行不同选择

wpf - 在按钮悬停时将文本和路径更改为不同的颜色

c# - 如何让 Visual Studio 识别 XAML 更改?

c# - 在 WP8 上更改按钮边框颜色时滞后

c# - c#中的日期计算

c# - 显示 Unity3d 广告后跟 Application.LoadLevel (Application.loadedLevel);

c# - 是什么导致 EF 插入比普通 ADO.NET 慢得多?