ICommand 依赖项 属性
ICommand Dependency Property
我有一个 UserControl,里面有一个按钮。此按钮需要将一些项目添加到所述 UC 内的网格中。我知道我可以通过 Click 事件来做到这一点。
这里的问题是我正在使用 MVVM 并且在相应的 ViewModel 之外更改数据会破坏格式(可以这么说)。
有没有办法创建 ICommand 依赖项 属性 以便我可以将所述 DP 绑定到按钮并具有将项目添加到我的 ViewModel 中的网格的功能? (我已经在我的 UC 和我的 ViewModel 中有了这个列表,它们正在按预期工作)
谢谢。
基本方法是创建一个实现 ICommand 的对象(即 MyCommand),并将其嵌套在您的 ViewModel 中。在 MyCommand 中,您无权访问 ViewModel。您可以解决它(即在 MyCommand 构造函数中传递对 ViewModel 的引用)但最终代码太多(对于像这样的简单内容)。我想几乎没有人真正这样做过。
大多数使用 DelegateCommand 解决(大部分)上述问题。
最后但同样重要的是,只需使用事件处理程序。
如果你像这样简单地编码它们:
void Grid_MouseMove(object sender, MouseEventArgs e)
{ viewModel.SaveMousePosition(e.GetPosition()); }
您没有违反任何 MVVM 规则。
而且你不能用命令来处理上面的事件。
MouseMove 没有 Command(大多数事件有 none),并且不能在 Command 中传递事件参数。
您可以使用 Interaction.Triggers 处理每个事件,例如 this
但是你仍然怀念处理事件参数的能力(并且添加丑陋的XAML)。
对我来说,直到 WPF 支持事件处理程序中的数据绑定,例如
Grid MouseMove="{Binding SaveMousePosition(e)}"
code behind 仍然是处理事件最有效的方法。
按照我尝试的方式找到了解决问题的方法。在这里留下答案,以便人们可以使用它:
1) 在您的用户控件的代码隐藏中,创建一个依赖项 属性。我选择 ICommand,因为在我的 ViewModel 中我将它设置为 DelegateCommmand:
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register(
"Command",
typeof(ICommand),
typeof(UserControl));
public ICommand Command
{
get
{
return (ICommand)GetValue(CommandProperty);
}
set
{
SetValue(CommandProperty, value);
}
}
2) 在您的 UserControl 的 XAML 代码中,绑定此依赖项 属性(在本例中为按钮):
<Grid DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}">
<Button Command="{Binding Command}" />
</Grid>
3) 接下来,在您的 ViewModel 上,声明一个命令 属性 并进行相应配置:
public ICommand ViewModelCommand { get; set; }
public ViewModelConstructor()
{
ViewModelCommand = new DelegateCommand(ViewModelCommandExecute);
}
private void ViewModelCommandExecute()
{
// Do something
}
4) 最后,在嵌套了 UserControl 的视图上,我们声明绑定:
<UserControls:UserControl Command={Binding ViewModelCommand}/>
这样,绑定就会发生,您可以将来自任何用户控件的按钮的命令绑定到您的 ViewModel,而不会破坏 MVVM。
我遇到了类似的问题,这个 question/answers 对我帮助最大;所以我将 post 我的解决方案放在这里,以防其他人稍后 google 它。用 mvvm light 制作。
我有一个自定义的 winforms 控件作为模型,一个 WPF 控件作为视图。所以,xaml 的视图(我的视图有一个用户控件,没有 app.xaml):
<UserControl.Resources>
<ResourceDictionary>
<viewModel:ViewModelLocator x:Key="Locator" />
</ResourceDictionary>
</UserControl.Resources>
<UserControl.DataContext>
<Binding Path = "Main" Source="{StaticResource Locator}"></Binding>
</UserControl.DataContext>
<Grid>
<Button Command="{Binding Zoom, ElementName=Wrapper}"></Button>
<viewModel:ProfileWrapper x:Name="Wrapper" >
</viewModel:ProfileWrapper>
</Grid>
按钮的点击被路由到 ProfileWrapper 中的 RelayCommand 缩放(这是我的模型实现的地方)
那么ProfileWrapper的xaml就很简单了:
<Grid>
<WindowsFormsHost>
<local:ManualControl x:Name="abc" ></local:ManualControl>
</WindowsFormsHost>
</Grid>
ProfileWrapper 的隐藏代码:
public partial class ProfileWrapper : UserControl
{
public ProfileWrapper()
{
InitializeComponent();
test = abc;
Command = new RelayCommand(() => test.bZoomIn());
}
public ManualControl test;
public RelayCommand Zoom { get; set; }
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register(
"Zoom",
typeof(ICommand),
typeof(ProfileWrapper));
public ICommand Command
{
get
{
return (ICommand)GetValue(CommandProperty);
}
set
{
SetValue(CommandProperty, value);
}
}
}
我的 MainViewModel class 是空的,所有功能都交给了 ProfileWrapper class,这可能很糟糕,但至少它有效。
我有一个 UserControl,里面有一个按钮。此按钮需要将一些项目添加到所述 UC 内的网格中。我知道我可以通过 Click 事件来做到这一点。
这里的问题是我正在使用 MVVM 并且在相应的 ViewModel 之外更改数据会破坏格式(可以这么说)。
有没有办法创建 ICommand 依赖项 属性 以便我可以将所述 DP 绑定到按钮并具有将项目添加到我的 ViewModel 中的网格的功能? (我已经在我的 UC 和我的 ViewModel 中有了这个列表,它们正在按预期工作)
谢谢。
基本方法是创建一个实现 ICommand 的对象(即 MyCommand),并将其嵌套在您的 ViewModel 中。在 MyCommand 中,您无权访问 ViewModel。您可以解决它(即在 MyCommand 构造函数中传递对 ViewModel 的引用)但最终代码太多(对于像这样的简单内容)。我想几乎没有人真正这样做过。
大多数使用 DelegateCommand 解决(大部分)上述问题。
最后但同样重要的是,只需使用事件处理程序。
如果你像这样简单地编码它们:
void Grid_MouseMove(object sender, MouseEventArgs e)
{ viewModel.SaveMousePosition(e.GetPosition()); }
您没有违反任何 MVVM 规则。
而且你不能用命令来处理上面的事件。
MouseMove 没有 Command(大多数事件有 none),并且不能在 Command 中传递事件参数。
您可以使用 Interaction.Triggers 处理每个事件,例如 this
但是你仍然怀念处理事件参数的能力(并且添加丑陋的XAML)。
对我来说,直到 WPF 支持事件处理程序中的数据绑定,例如
Grid MouseMove="{Binding SaveMousePosition(e)}"
code behind 仍然是处理事件最有效的方法。
按照我尝试的方式找到了解决问题的方法。在这里留下答案,以便人们可以使用它:
1) 在您的用户控件的代码隐藏中,创建一个依赖项 属性。我选择 ICommand,因为在我的 ViewModel 中我将它设置为 DelegateCommmand:
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register(
"Command",
typeof(ICommand),
typeof(UserControl));
public ICommand Command
{
get
{
return (ICommand)GetValue(CommandProperty);
}
set
{
SetValue(CommandProperty, value);
}
}
2) 在您的 UserControl 的 XAML 代码中,绑定此依赖项 属性(在本例中为按钮):
<Grid DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}">
<Button Command="{Binding Command}" />
</Grid>
3) 接下来,在您的 ViewModel 上,声明一个命令 属性 并进行相应配置:
public ICommand ViewModelCommand { get; set; }
public ViewModelConstructor()
{
ViewModelCommand = new DelegateCommand(ViewModelCommandExecute);
}
private void ViewModelCommandExecute()
{
// Do something
}
4) 最后,在嵌套了 UserControl 的视图上,我们声明绑定:
<UserControls:UserControl Command={Binding ViewModelCommand}/>
这样,绑定就会发生,您可以将来自任何用户控件的按钮的命令绑定到您的 ViewModel,而不会破坏 MVVM。
我遇到了类似的问题,这个 question/answers 对我帮助最大;所以我将 post 我的解决方案放在这里,以防其他人稍后 google 它。用 mvvm light 制作。
我有一个自定义的 winforms 控件作为模型,一个 WPF 控件作为视图。所以,xaml 的视图(我的视图有一个用户控件,没有 app.xaml):
<UserControl.Resources>
<ResourceDictionary>
<viewModel:ViewModelLocator x:Key="Locator" />
</ResourceDictionary>
</UserControl.Resources>
<UserControl.DataContext>
<Binding Path = "Main" Source="{StaticResource Locator}"></Binding>
</UserControl.DataContext>
<Grid>
<Button Command="{Binding Zoom, ElementName=Wrapper}"></Button>
<viewModel:ProfileWrapper x:Name="Wrapper" >
</viewModel:ProfileWrapper>
</Grid>
按钮的点击被路由到 ProfileWrapper 中的 RelayCommand 缩放(这是我的模型实现的地方)
那么ProfileWrapper的xaml就很简单了:
<Grid>
<WindowsFormsHost>
<local:ManualControl x:Name="abc" ></local:ManualControl>
</WindowsFormsHost>
</Grid>
ProfileWrapper 的隐藏代码:
public partial class ProfileWrapper : UserControl
{
public ProfileWrapper()
{
InitializeComponent();
test = abc;
Command = new RelayCommand(() => test.bZoomIn());
}
public ManualControl test;
public RelayCommand Zoom { get; set; }
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register(
"Zoom",
typeof(ICommand),
typeof(ProfileWrapper));
public ICommand Command
{
get
{
return (ICommand)GetValue(CommandProperty);
}
set
{
SetValue(CommandProperty, value);
}
}
}
我的 MainViewModel class 是空的,所有功能都交给了 ProfileWrapper class,这可能很糟糕,但至少它有效。