Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用MVVM在xaml中进行命令绑定_C#_Wpf_Xaml_Mvvm - Fatal编程技术网

C# 使用MVVM在xaml中进行命令绑定

C# 使用MVVM在xaml中进行命令绑定,c#,wpf,xaml,mvvm,C#,Wpf,Xaml,Mvvm,目前,我正在尝试使用C#、WPF、MVVM创建我的第一个Windows应用程序,请参见下图 我的文件结构: 该应用程序的目标是在左侧有一个导航菜单,可用于导航到不同的内容,这些内容必须显示在白色区域中(见上图) 导航菜单中的“菜单项”(左侧的6个按钮)用于更改白色区域中显示的内容。我使用以下代码创建这些按钮: class MenuItemViewModel:BaseViewModel { public MenuItemViewModel(string ItemName, string

目前,我正在尝试使用C#、WPF、MVVM创建我的第一个Windows应用程序,请参见下图

我的文件结构:

该应用程序的目标是在左侧有一个导航菜单,可用于导航到不同的内容,这些内容必须显示在白色区域中(见上图)

导航菜单中的“菜单项”(左侧的6个按钮)用于更改白色区域中显示的内容。我使用以下代码创建这些按钮:

class MenuItemViewModel:BaseViewModel
{
    public MenuItemViewModel(string ItemName, string ItemImage, ICommand Command)
    {
        _MenuItem = new MenuItemModel(ItemName, ItemImage);
        _command = Command;
    }

    private MenuItemModel _MenuItem;
    public ICommand _command;

    public MenuItemModel MenuItem
    {
        get { return _MenuItem; }
    }

    public ICommand Command
    {
        get { return _command; }
    }


} // Class
在my Main Window.xaml中,我使用“ItemsControl”将“ItemsForce”绑定到菜单项列表

MainWindows.xaml:

<Window x:Class="TSD.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:TSD"
    xmlns:ViewModels="clr-namespace:TSD.ViewModels"
    xmlns:views="clr-namespace:TSD.Views"
    mc:Ignorable="d"
    Title="TS Dashboard" Height="600" Width="1025" WindowStartupLocation="CenterScreen"
    WindowStyle="None"
    ResizeMode="CanResize"
    WindowState="Normal"
    >

<Window.Resources>
</Window.Resources>

<WindowChrome.WindowChrome>
    <WindowChrome 
    CaptionHeight="0"
    ResizeBorderThickness="5"/>
</WindowChrome.WindowChrome>

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="25"/>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="auto"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>

    <Grid Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Background="#2b6ea4" MouseDown="Window_MouseDown">
        <TextBlock x:Name="mainwindow_title" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="20,0,0,0" Text="{Binding MainWindowText}">
        </TextBlock>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Width="75">
            <Button Background="Transparent" BorderThickness="0" Width="25" Name="min_button" Click="MinimizeButton_Click">
                <Image Source="/assets/mini.png" Height="10" Width="10"/>
            </Button>
            <Button Background="Transparent" BorderThickness="0" Width="25" Name="max_button" Click="MaximizeButton_Click">
                <Image Source="/assets/max.png" Height="10" Width="10"/>
            </Button>
            <Button Background="Transparent" BorderThickness="0" Width="25" Name="close_button" Click="CloseButton_Click">
                <Image Source="/assets/close.png" Height="10" Width="10"/>
            </Button>
        </StackPanel>
    </Grid>

    <Grid Grid.Column="0" Margin="0,0,0,0" Grid.Row="2">
        
        <Grid.RowDefinitions>
            <RowDefinition Height="100"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        
        <Image Grid.Row="0" Source="{Binding ImagePath}"></Image>

        <ItemsControl Background="#2B6EA4" Grid.Row="1" x:Name="NavigationMenu" ItemsSource="{Binding MenuItems}" Width="auto" HorizontalContentAlignment="Stretch">
            
        </ItemsControl>
        
    </Grid>
    
    <Grid Grid.Column="1" Margin="0,0,0,0" Grid.Row="2">
        <ContentControl Content="{Binding CurrentViewModel}">
            <ContentControl.Resources>
                <DataTemplate DataType="{x:Type ViewModels:HcfContentViewModel}">
                    <views:UserControlHcfContent/>
                </DataTemplate>
                <DataTemplate DataType="{x:Type ViewModels:SLDContentViewModel}">
                    <views:UserControlSLDContent/>
                </DataTemplate>
            </ContentControl.Resources>
        </ContentControl>
    </Grid>
    
</Grid>
在我的MainWindowViewModel中,我创建了一个UserControl列表,每个UserControl代表导航菜单中的一个按钮,该列表称为_menuItems,并绑定到前面显示的ItemsControl

MainWindowViewModel.cs:

class MainWindowViewModel : BaseViewModel, INotifyPropertyChanged
{

    public MainWindowViewModel(NavigationStore navigationStore)
    {
        //Set name for window.
        _MainWindowText = "My first MVVM application";
        _ImagePath = "/assets/placeholder_image_name.png";

        //Create MenuItems
        UserControlMenuItem Item1 = new UserControlMenuItem(dummyCommand, "ISSUE LIST", "/assets/issue_list_icon.png");
        UserControlMenuItem Item2 = new UserControlMenuItem(dummyCommand, "SYSTEM SHORTLOG DOWNLOAD","/assets/sld_icon.jpg");
        UserControlMenuItem Item3 = new UserControlMenuItem(navigateHcfCommand, "HOSE CONNECTION FINDER", "/assets/hose_icon.png");
        UserControlMenuItem Item4 = new UserControlMenuItem(dummyCommand, "GET CONFIG", "/assets/config_icon.png");
        UserControlMenuItem Item5 = new UserControlMenuItem(dummyCommand, "KNOWLEDGE TRANSFER", "/assets/knowledge_transfer_icon.png");
        UserControlMenuItem Item6 = new UserControlMenuItem(dummyCommand, "AMBITION LISTS", "/assets/ambition_list_icon.png");
        
        //Properties
        _MenuItems = new List<UserControlMenuItem> { Item1, Item2, Item3, Item4, Item5, Item6 };
        _navigationStore = navigationStore;

        //Commands used in this view
        dummyCommand = new DummyCommand();
        navigateHcfCommand = new ShowHcfCommand(_navigationStore);
    }

    // Class fields
    private string _MainWindowText;
    private List<UserControlMenuItem> _MenuItems;
    private string _ImagePath;
    private readonly NavigationStore _navigationStore;
    // Commands
    public ICommand navigateHcfCommand;
    public ICommand dummyCommand;


    //Class properties
    public string ImagePath
    {
        get => _ImagePath;
        set {
            _ImagePath = ImagePath;
            OnPropertyChanged("ImagePath");
        }
    }

    public string MainWindowText
    {
        get => _MainWindowText;
        set {
            _MainWindowText = value;
            OnPropertyChanged("MainWindowText");
        }
    }

    public List<UserControlMenuItem> MenuItems
    {
        get => _MenuItems;
        set {
            _MenuItems = value;
            OnPropertyChanged("MenuItems");
        }
    }

    public BaseViewModel CurrentViewModel
    {
        get => _navigationStore.CurrentViewModel;
        set { _navigationStore.CurrentViewModel = value; }
    }

    public ICommand UpdateCommand
    {
        get;
        private set;
    }

    //
    // Events
    //

    //Declare the event
    public event PropertyChangedEventHandler PropertyChanged;

    // Create the OnPropertyChanged method to raise the event
    // The calling member's name will be used as the parameter.
    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}// Class
以及menuitemodel.cs:

class MenuItemModel : INotifyPropertyChanged
{

    private string _ItemName;
    private string _ItemImage;

    public MenuItemModel(string itemname, string itemimage)
    {
        _ItemName = itemname;
        _ItemImage = itemimage;
    }

    public string ItemName
    {
        get => _ItemName;
        set {
            _ItemName = value;
            OnPropertyChanged("ItemName");
        }
    }

    public string ItemImage
    {
        get => _ItemImage;
        set {
            _ItemImage = value;
            OnPropertyChanged("ItemImage");
        }
    }

    //
    // Events
    //

    //Declare the event
    public event PropertyChangedEventHandler PropertyChanged;

    // Create the OnPropertyChanged method to raise the event
    // The calling member's name will be used as the parameter.
    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
从第一张图片可以看出,这工作正常,问题在于绑定命令以更改“内容区域”(白色区域第一张图片)

我将在这里简要介绍内容区的代码: 在MainWindow.xaml(第一个代码段)中,您将看到一个“ContentControl”,这里我绑定了CurrentViewModel,它表示要在内容区域中显示的内容。我使用navigationStore存储必须显示的ViewModel

navigationStore.cs:

public class NavigationStore
{
    public BaseViewModel CurrentViewModel { get; set; }
}
以及“内容页”的示例: 视图:

型号:

class HcfContentModel : INotifyPropertyChanged
{

    private string _activeProductName;
    private int _availableProducts;
    
    public HcfContentModel()
    {

    }

    public string activeProductName
    {
        get => _activeProductName;
        set 
        {
            _activeProductName = value;
            OnPropertyChanged("activeProductName");
        }
    }

    public int availableProducts
    {
        get => _availableProducts;
        set 
        {
            _availableProducts = value;
            OnPropertyChanged("availableProducts");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
问题陈述:

按下/单击导航菜单中的项菜单时,不会触发命令。 我正在尝试执行ShowHcfCommand以将内容区域更改为HcfViewModel

ShowHcfCommand:

class ShowHcfCommand : BaseCommand
{
    private readonly NavigationStore _navigationStore;

    public ShowHcfCommand(NavigationStore navigationStore)
    {
        _navigationStore = navigationStore;
    }

    public override void Execute(object parameter)
    {
        _navigationStore.CurrentViewModel = new HcfContentViewModel();
        Console.WriteLine("Command Executed!");
    }
}
我希望提供的信息是充分和明确的,如果没有,请让我知道,以便我可以更新它。 可以从my github页面克隆整个项目:

我正在使用VS2017

如果有关于如何改进项目总体布局的提示,请让我知道

提前谢谢。 亲切问候,,
Sam

在MainWindowViewModel.cs中,您从未实例化命令的实例

public ICommand navigateHcfCommand; //not instantiated
但在构造函数中使用:

       UserControlMenuItem Item3 = new UserControlMenuItem(navigateHcfCommand, "HOSE CONNECTION FINDER", "/assets/hose_icon.png");
菜单项绑定到空命令。
如果更改,它仍然不会显示正确的contentviewmodel,因为您没有从navigationstore类调用property changed或任何其他事件。首先,感谢您的帮助

在听了T.Schwarz的评论后,我设法让它工作起来

我更新了MainWindowViewModel.cs以修复分配的null命令。 这最初修复了命令未被执行的问题,但正如T.Schwarz所提到的,它仍然不会改变视图。我必须在MainWindowViewModel中通知更改的属性,而不是从navigationStore。更新后的MainWindowViewModel如下所示:

class MainWindowViewModel : BaseViewModel, INotifyPropertyChanged
{

    // Class fields
    private string _MainWindowText;
    private List<UserControlMenuItem> _MenuItems;
    private string _ImagePath;
    private readonly NavigationStore _navigationStore;

    // Commands
    public ICommand navigateHcfCommand;
    public ICommand dummyCommand;


    public MainWindowViewModel(NavigationStore navigationStore)
    {
        //Stores
        _navigationStore = navigationStore;

        //Commands used in this view
        dummyCommand = new DummyCommand();
        navigateHcfCommand = new ShowHcfCommand(this);

        //Set name for window.
        _MainWindowText = "My first MVVM application";
        _ImagePath = "/assets/placeholder_image_name.png";

        //Create MenuItems
        UserControlMenuItem Item1 = new UserControlMenuItem(dummyCommand, "ISSUE LIST", "/assets/issue_list_icon.png");
        UserControlMenuItem Item2 = new UserControlMenuItem(dummyCommand, "SYSTEM SHORTLOG DOWNLOAD","/assets/sld_icon.jpg");
        UserControlMenuItem Item3 = new UserControlMenuItem(navigateHcfCommand, "HOSE CONNECTION FINDER", "/assets/hose_icon.png");
        UserControlMenuItem Item4 = new UserControlMenuItem(dummyCommand, "GET CONFIG", "/assets/config_icon.png");
        UserControlMenuItem Item5 = new UserControlMenuItem(dummyCommand, "KNOWLEDGE TRANSFER", "/assets/knowledge_transfer_icon.png");
        UserControlMenuItem Item6 = new UserControlMenuItem(dummyCommand, "AMBITION LISTS", "/assets/ambition_list_icon.png");
        
        //Properties
        _MenuItems = new List<UserControlMenuItem> { Item1, Item2, Item3, Item4, Item5, Item6 };
    }


    //Class properties
    public string ImagePath
    {
        get => _ImagePath;
        set {
            _ImagePath = ImagePath;
            OnPropertyChanged("ImagePath");
        }
    }

    public string MainWindowText
    {
        get => _MainWindowText;
        set {
            _MainWindowText = value;
            OnPropertyChanged("MainWindowText");
        }
    }

    public List<UserControlMenuItem> MenuItems
    {
        get => _MenuItems;
        set {
            _MenuItems = value;
            OnPropertyChanged("MenuItems");
        }
    }

    public BaseViewModel CurrentViewModel
    {
        get => _navigationStore.CurrentViewModel;
        set {
            _navigationStore.CurrentViewModel = value;
            OnPropertyChanged("CurrentViewModel");
        }
    }

    public ICommand UpdateCommand
    {
        get;
        private set;
    }

    //
    // Events
    //

    //Declare the event
    public event PropertyChangedEventHandler PropertyChanged;

    // Create the OnPropertyChanged method to raise the event
    // The calling member's name will be used as the parameter.
    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}// Class
class MainWindowViewModel:BaseViewModel,INotifyPropertyChanged
{
//类字段
私有字符串MainWindowText;
私有列表(菜单项);;
私有字符串_ImagePath;
私有只读NavigationStore_NavigationStore;
//命令
公共ICommand和NavigateHCcommand;
公共ICommand dummyCommand;
公共主窗口视图模型(导航存储导航存储)
{
//商店
_导航存储=导航存储;
//此视图中使用的命令
dummyCommand=新的dummyCommand();
navigateHcfCommand=新的ShowHcfCommand(本);
//设置窗口的名称。
_MainWindowText=“我的第一个MVVM应用程序”;
_ImagePath=“/assets/placeholder\u image\u name.png”;
//创建菜单项
UserControlMenuItem1=新的UserControlMenuItem(dummyCommand,“问题列表”,“assets/ISSUE\u LIST\u icon.png”);
UserControlMenuItem2=新的UserControlMenuItem(dummyCommand,“系统短日志下载”,“/assets/sld_icon.jpg”);
UserControlMenuItem3=新的UserControlMenuItem(navigateHcfCommand,“软管连接查找器”、“/assets/HOSE_icon.png”);
UserControlMenuItem4=新的UserControlMenuItem(dummyCommand,“GET-CONFIG”,“/assets/CONFIG_-icon.png”);
UserControlMenuItem5=新的UserControlMenuItem(dummyCommand,“知识转移”,“assets/KNOWLEDGE\u TRANSFER\u icon.png”);
UserControlMenuItem6=新的UserControlMenuItem(dummyCommand,“野心列表”,“资产/野心列表图标.png”);
//性质
_MenuItems=新列表{Item1,Item2,Item3,Item4,Item5,Item6};
}
//类属性
公共字符串映像路径
{
get=>\u ImagePath;
设置{
_ImagePath=ImagePath;
OnPropertyChanged(“ImagePath”);
}
}
公共字符串MainWindowText
{
get=>\u MainWindowText;
设置{
_MainWindowText=值;
OnPropertyChanged(“MainWindowText”);
}
}
公共列表菜单项
{
获取=>\u菜单项;
设置{
_MenuItems=值;
OnPropertyChanged(“菜单项”);
}
}
公共基础视图模型CurrentViewModel
{
get=>\u navigationStore.CurrentViewModel;
设置{
_navigationStore.CurrentViewModel=值;
OnPropertyChanged(“CurrentViewModel”);
}
}
公共ICommand更新命令
{
收到
私人设置;
}
//
//事件
//
//宣布事件
公共事件属性更改事件处理程序属性更改;
//创建OnPropertyChanged方法以引发事件
//调用成员的名称将用作参数。
受保护的无效OnPropertyChanged(字符串propertyName)
{
if(PropertyChanged!=null)
{
PropertyChanged(这是新的PropertyChangedEventArgs(propertyName));
}
}
}//阶级
正如您从上面的代码中看到的,我现在将MainWindowViewModel传递给ShowHcfCommand,在这个命令中我更改了v
class ShowHcfCommand : BaseCommand
{
    private readonly NavigationStore _navigationStore;

    public ShowHcfCommand(NavigationStore navigationStore)
    {
        _navigationStore = navigationStore;
    }

    public override void Execute(object parameter)
    {
        _navigationStore.CurrentViewModel = new HcfContentViewModel();
        Console.WriteLine("Command Executed!");
    }
}
public ICommand navigateHcfCommand; //not instantiated
       UserControlMenuItem Item3 = new UserControlMenuItem(navigateHcfCommand, "HOSE CONNECTION FINDER", "/assets/hose_icon.png");
class MainWindowViewModel : BaseViewModel, INotifyPropertyChanged
{

    // Class fields
    private string _MainWindowText;
    private List<UserControlMenuItem> _MenuItems;
    private string _ImagePath;
    private readonly NavigationStore _navigationStore;

    // Commands
    public ICommand navigateHcfCommand;
    public ICommand dummyCommand;


    public MainWindowViewModel(NavigationStore navigationStore)
    {
        //Stores
        _navigationStore = navigationStore;

        //Commands used in this view
        dummyCommand = new DummyCommand();
        navigateHcfCommand = new ShowHcfCommand(this);

        //Set name for window.
        _MainWindowText = "My first MVVM application";
        _ImagePath = "/assets/placeholder_image_name.png";

        //Create MenuItems
        UserControlMenuItem Item1 = new UserControlMenuItem(dummyCommand, "ISSUE LIST", "/assets/issue_list_icon.png");
        UserControlMenuItem Item2 = new UserControlMenuItem(dummyCommand, "SYSTEM SHORTLOG DOWNLOAD","/assets/sld_icon.jpg");
        UserControlMenuItem Item3 = new UserControlMenuItem(navigateHcfCommand, "HOSE CONNECTION FINDER", "/assets/hose_icon.png");
        UserControlMenuItem Item4 = new UserControlMenuItem(dummyCommand, "GET CONFIG", "/assets/config_icon.png");
        UserControlMenuItem Item5 = new UserControlMenuItem(dummyCommand, "KNOWLEDGE TRANSFER", "/assets/knowledge_transfer_icon.png");
        UserControlMenuItem Item6 = new UserControlMenuItem(dummyCommand, "AMBITION LISTS", "/assets/ambition_list_icon.png");
        
        //Properties
        _MenuItems = new List<UserControlMenuItem> { Item1, Item2, Item3, Item4, Item5, Item6 };
    }


    //Class properties
    public string ImagePath
    {
        get => _ImagePath;
        set {
            _ImagePath = ImagePath;
            OnPropertyChanged("ImagePath");
        }
    }

    public string MainWindowText
    {
        get => _MainWindowText;
        set {
            _MainWindowText = value;
            OnPropertyChanged("MainWindowText");
        }
    }

    public List<UserControlMenuItem> MenuItems
    {
        get => _MenuItems;
        set {
            _MenuItems = value;
            OnPropertyChanged("MenuItems");
        }
    }

    public BaseViewModel CurrentViewModel
    {
        get => _navigationStore.CurrentViewModel;
        set {
            _navigationStore.CurrentViewModel = value;
            OnPropertyChanged("CurrentViewModel");
        }
    }

    public ICommand UpdateCommand
    {
        get;
        private set;
    }

    //
    // Events
    //

    //Declare the event
    public event PropertyChangedEventHandler PropertyChanged;

    // Create the OnPropertyChanged method to raise the event
    // The calling member's name will be used as the parameter.
    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}// Class