我的观点包含Button
和UserControl
。 UserControl
还包含Button
。我视图中的Button1和UserControl
中的Button2都应该在ViewModel中调用相同的方法。
因此,我需要RelayCommand
向UserControl
“注入”(不知道如何调用它)。我认为依赖属性会很容易,但我无法让它工作。
我尝试了什么:
UserControl
包含依赖项属性,该属性在包含UserControl
的视图的XAML代码中设置:
UserControl代码:
public const string LoadDataCommandPropertyName = "LoadDataCommand";
public Action LoadDataCommand
{
get
{
return (Action)GetValue(LoadDataCommandProperty);
}
set
{
SetValue(LoadDataCommandProperty, value);
}
}
public static readonly DependencyProperty LoadDataCommandProperty = DependencyProperty.Register(
LoadDataCommandPropertyName,
typeof(Action),
typeof(GridViewPersistenceController),
new UIPropertyMetadata());
查看Xaml代码:(在UserControl中使用dp)
<customControls:MyUserControl Grid.Column="1"
x:Name="RadGridViewSettingsPersistenceControl"
GridControl="{Binding ElementName=RadGridView}"
LoadDataCommand="{Binding ActionTest}"
/>
UserControl的LoadDataCommand绑定到ViewModel中的此属性
private const string ActionTestPropertyName = "ActionTest";
private Action actionTest;
public Action ActionTest
{
get
{
return this.actionTest;
}
set
{
this.RaisePropertyChanging(ActionTestPropertyName);
this.actionTest = value;
this.RaisePropertyChanged(ActionTestPropertyName);
}
}
ActionTest属性在ViewModel
的构造函数中初始化public MyViewModel()
{
this.ActionTest = new Action(this.LoadData);
}
visual studio输出窗口也给了我一个绑定错误(我不明白)
System.Windows.Data错误:40:BindingExpression路径错误: 'object'''MyUserControl'上找不到'ActionTest'属性 (名称= 'RadGridViewSettingsPersistenceControl')”。 BindingExpression:路径= ActionTest;的DataItem = '的MyUserControl' (名称= 'RadGridViewSettingsPersistenceControl');目标元素是 'MyUserControl'(Name ='RadGridViewSettingsPersistenceControl');目标 property是'LoadDataCommand'(输入'Action')
我发现了一种有效的解决方法,但我不喜欢它。我在View codebehind的LoadedEvent中设置了LoadDataCommand。它看起来很麻烦,我觉得我错过了一些重要的概念。
//TODO: Dirty coding, fix me
private void MyView_OnLoaded(object sender, RoutedEventArgs e)
{
this.RadGridViewSettingsPersistenceControl.LoadDataCommand = new Action((this.DataContext as MyViewModel).LoadData);
}
问题:
Command
/ Action
传递给UserControl?答案 0 :(得分:5)
从错误中可以看出:
在'对象'''MyUserControl'上找不到'ActionTest'属性 (名称= 'RadGridViewSettingsPersistenceControl')'
绑定引擎正在搜索控件中的属性,而不是在ViewModel中搜索。 (默认情况下,它在DataContext控件中搜索属性,我怀疑你已经在代码中的某个地方设置了控件的DataContext)
使用 RelativeSource获取UserControl的DataContext ,这将是您的ViewModel。
LoadDataCommand="{Binding DataContext.ActionTest,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=UserControl}}"
此外,不是创建Action
类型的DP,而是使用ICommand
并在ViewModel中创建ICommand并绑定到它。
答案 1 :(得分:2)
作为替代方案,您可以使用附加依赖项属性。以下是一个例子:
AttachedDependencyProperty
public static class UserControlExtension
{
public static readonly DependencyProperty ActionProperty;
public static void SetAction(DependencyObject DepObject, ICommand value)
{
DepObject.SetValue(ActionProperty, value);
}
public static ICommand GetAction(DependencyObject DepObject)
{
return (ICommand)DepObject.GetValue(ActionProperty);
}
static UserControlExtension()
{
ActionProperty = DependencyProperty.RegisterAttached("Action",
typeof(ICommand),
typeof(UserControlExtension));
}
}
TestViewModel
public class TestViewModel
{
private ICommand _testButtonCommand = null;
public ICommand TestButtonCommand
{
get
{
if (_testButtonCommand == null)
{
_testButtonCommand = new RelayCommand(param => this.TestButton(), null);
}
return _testButtonCommand;
}
}
private void TestButton()
{
MessageBox.Show("Test command execute");
}
}
MainWindow
为View
<Window.Resources>
<local:TestViewModel x:Key="TestVM" />
</Window.Resources>
<Grid DataContext="{StaticResource TestVM}">
<local:TestUserControl x:Name="TestUserControl"
AttachedProperties:UserControlExtension.Action="{Binding TestButtonCommand}" />
</Grid>
UserControl
<Grid>
<Button Name="TestButton"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="TestContent"
Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}},
Path=(AttachedProperties:UserControlExtension.Action)}" />
</Grid>
示例项目可用here。