c# - 将 Action 注入(inject) UserControl

标签 c# wpf mvvm command dependency-properties

我的 View 包含一个 Button 和一个 UserControlUserControl 还包含一个 Button。我的 View 中的 Button1 和我的 UserControl 中的 Button2 都应该在 ViewModel 中调用相同的方法。

ViewViewModelUserControl

因此我需要将 RelayCommand“注入(inject)”(不知道如何调用它)到 UserControl 中。我认为使用依赖属性会很容易,但我无法让它工作。

我尝试了什么:

UserControl 包含一个依赖属性,该属性在包含 UserControl 的 View 的 XAML 代码中设置:

用户控制代码:

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 绑定(bind)到 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 输出窗口也给了我一个绑定(bind)错误(我不明白)

System.Windows.Data Error: 40 : BindingExpression path error: 'ActionTest' property not found on 'object' ''MyUserControl' (Name='RadGridViewSettingsPersistenceControl')'. BindingExpression:Path=ActionTest; DataItem='MyUserControl' (Name='RadGridViewSettingsPersistenceControl'); target element is 'MyUserControl' (Name='RadGridViewSettingsPersistenceControl'); target property is 'LoadDataCommand' (type 'Action')

我找到了一个可行的解决方法,但我不喜欢它。我在 View 代码隐藏的 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);
    }

问题:

  • 如何使用 View 中的 xaml 代码将 ViewModel 中定义的 Command/Action 传递到 UserControl?
  • 为什么我当前的绑定(bind)方法不起作用?
  • 我是否遗漏了一些基本概念? (我可以通过代表更轻松地实现这一点吗?(我试过..))

最佳答案

从错误中可以明显看出:

'ActionTest' property not found on 'object' ''MyUserControl' (Name='RadGridViewSettingsPersistenceControl')'

绑定(bind)引擎正在控件中搜索属性,而不是在您的 ViewModel 中搜索。 (默认情况下,它在控件的 DataContext 中搜索属性,我怀疑您已经在代码中的某处将控件的 DataContext 设置为自身)

使用 RelativeSource 获取您的 UserControl 的 DataContext,这将是您的 ViewModel。

LoadDataCommand="{Binding DataContext.ActionTest,
                   RelativeSource={RelativeSource Mode=FindAncestor,
                                           AncestorType=UserControl}}"

此外,不要创建 Action 类型的 DP,而是使用 ICommand 并在您的 ViewModel 中创建 ICommand 并绑定(bind)到它。

关于c# - 将 Action 注入(inject) UserControl,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21278781/

相关文章:

c# - 在 visual studio 2010 中自动生成一个 try catch block

c# - 请在特定于平台的项目中调用 CachedImageRenderer.Init 方法以使用 FFImageLoading?

c# - 如何识别调用存储过程

c# - 如何在 XBAP 或 ClickOnce 应用程序中获取引荐来源网址?

wpf - 使用 MVVM 过滤 WPF TreeView

c# - Delegatecommand、relaycommand、routedcommand的区别

android - 观察 onCreate fragment 时调用的 LiveData

c# - DateTime.ToString 格式化并将结果字符串反转回日期时间

wpf - 类型 'Window'不支持直接内容

wpf - 取消异步 WCF 请求的最佳方法是什么?