C#WPF将来自不同用户控件的属性用作命令参数

时间:2018-08-23 12:13:40

标签: c# wpf mvvm

我在MVVM WPF应用程序中引用不同用户控件上的属性或元素时遇到问题。

编辑:将代码简化为MCVE(希望如此)。还删除了PropertyChanged事件以减少代码。

TLDR

  • 我将所有MainWindow.xaml元素拆分为不同的用户控件
  • 在菜单栏中(一个控件),我想触发一个ICommand来保存一个Settings对象(这是MainWindow的数据上下文
  • 对于Command中调用的方法,我需要来自完全不同的UserControl的值,该控件既不是菜单栏的父项也不是子菜单项

如何使用MVVM方法(最好是作为MenuBar上的CommandParameter)从PasswordBox中检索值?

查看

MainWindow.xaml

<Window x:Class="WpfApp1.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:WpfApp1.ViewModel"
        xmlns:View="clr-namespace:WpfApp1.View"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <ViewModel:SettingsViewModel/>
    </Window.DataContext>
    <StackPanel>
        <DockPanel>
            <View:MenuBar DataContext="{Binding}"/>
        </DockPanel>

        <TabControl>
            <TabItem Header="Tab1" DataContext="{Binding AppSettings}">
                <View:TabItemContent/>
            </TabItem>
        </TabControl>
    </StackPanel>
</Window>

应该绑定到ViewModel(MainWindow的DataContext)的ICommand属性上的MenuBar。

MenuBar.xaml

<UserControl x:Class="WpfApp1.View.MenuBar"
             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:WpfApp1.View"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800" >
    <Menu DockPanel.Dock="Top" Height="Auto" >
          <!-- In the command I need a reference to the password on the tabItem -->
        <MenuItem Name="SaveItem" Height="Auto" Header="Save"
                Command="{Binding SaveCommand}"
                CommandParameter="Binding RelativeSource=
        {RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"/>
    </Menu>
</UserControl>

TabItemContent.xaml

<UserControl x:Class="WpfApp1.View.TabItemContent"
             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:WpfApp1.View"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800"
             DataContext="{Binding PasswordSettings}">
    <Grid>
        <PasswordBox Height="25" Width="100" />
    </Grid>
</UserControl>

TabItemControl.xaml.cs 中,我试图引入依赖项属性并将其值设置为控件的数据上下文。

ViewModel

SettingViewModel.cs

using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;

using WpfApp1.Commands;
using WpfApp1.Model;

namespace WpfApp1.ViewModel
{
  public class SettingsViewModel
  {    
    public Settings AppSettings { get; private set; } = new Settings();
    public ICommand SaveCommand { get; private set; }

    public SettingsViewModel()
    {
      SaveCommand = new DelegateCommand( SaveSettings );

      // load settings and call
      // OnPropertyChanged( "AppSettings" );
    }


    public void SaveSettings( object o = null )
    {
      if( o is string encryptedPass )
      {
        // get the password and save it to AppSettings object
      }

      // call save method on settings
    }
  }
}

模型(设置类)

AppSetting.cs (封装了其他标签中的所有设置对象)

namespace WpfApp1.Model
{
  public class Settings
  {
    public PasswordSettings PwSettings { get; set; } = new PasswordSettings();

  }
}

PasswordSettings.cs

namespace WpfApp1.Model
{
  public class PasswordSettings
  {
    public string EncryptedPass { get; set; }

  }
}

最后是
中的DelegateCommand实现 DelegateCommand.cs 参见this gist

0 个答案:

没有答案