c# - 有没有办法以编程方式绑定(bind)到 InputBinding Command 属性?

标签 c# wpf xaml mvvm

我知道这是一个通用标题,但我的问题很具体。我认为这将归结为实践问题。所以,我有以下代码:

public partial class MainWindow : Window
{
    InitializeComponent();
    MyViewModel viewModel = new MyViewModel();
    this.myGrid.DataContext = viewModel;
}

public class MyViewModel
{
    public ICommand SomeCommandProperty { get { return this.someCommandProperty; }}
}

public class ComponentCollection : Panel
{
    public ComponentCollection()
    {
        for (int i = 0; i < n; i++)
        {
            this.Children.Add(new Component());
        }
    }
}

public class Component : UIElement
{
    public Component()
    {
        this.InputBindings.Add(new MouseBinding(SomeCommandProperty, new MouseGesture(MouseAction.LeftClick)));
    }
}

我可以轻松地将拥有 SomeCommandProperty 的 ViewModel 聚合到 Component 类中,但我目前放弃该选项,假设还有另一种方法。

Component 是 ComponentCollection 的子项,ComponentCollection 是 DataContext 为 MyViewModel 的 Grid 的子项。 ComponentCollection 顾名思义包含组件的集合。

<Grid Name="myGrid">
    <someNamespace:ComponentCollection x:Name="componentCollection"/>
</Grid>

它与下面的 XAML 相同,但使用了 TextBlock。我想我正在尝试以编程方式复制在下面的 XAML 中所做的事情。同样,组件的最高祖先的 DataContext 设置为 ViewModel。

<Grid Name="myGrid">
    <TextBlock Text="SomeText">
        <TextBlock.InputBindings>
            <MouseBinding Command="{Binding SomeCommandProperty}" MouseAction="LeftClick" />
        </TextBlock.InputBindings>
    </TextBlock>
</Grid>

更新 1

基本上,我有一个自定义控件,它继承自 Panel,其子项是 Component 的集合。这不是 hack,就像我提到的那样,如果我将 ViewModel 聚合到组件中,我可以直接访问 SomeCommandProperty。然而,这样做感觉很恶心。也就是说,可以从模型直接访问 ViewModel。

我想我要问的问题是。考虑到 Component 的父 UIElement 的 DataContext 设置为 MyViewModel 的情况,是否可以在 Component 不拥有对 的引用的情况下访问 SomeCommandProperty拥有 SomeCommandPropertyMyViewModel?也就是说,以编程方式。

使用 ItemsControl 不会改变我仍然需要将 SomeCommandProperty 绑定(bind)到每个 Items 的事实。

更新 2

见上面的代码。

更新 3

显然,据我所知,没有一种机制可以在 InputBinding 的 Command 属性上设置绑定(bind)。

例如,如果我的组件类继承自 ButtonBase 而不是 UIElement,我将拥有 Command 属性,我可以使用 FrameWorkElement 的 SetBinding 轻松地以编程方式设置绑定(bind)。不幸的是,我无法使用 InputBinding 的命令属性执行此操作。

public class Component : ButtonBase
{
    public Component()
    {
        System.Windows.Data.Binding binding = new System.Windows.Data.Binding
        {
            RelativeSource = new System.Windows.Data.RelativeSource(System.Windows.Data.RelativeSourceMode.FindAncestor, typeof(ComponentCollection), 1 ),
            Path = new PropertyPath("DataContext.SomeCommandProperty")
        };

        // I can do this.
        this.SetBinding(this.CommandProperty, binding);

        // But I want to do something like below.  Note: It's a pseudo code.
        MouseBinding mouseBinding = new MouseBinding();
        mouseBinding.SetBinding(mouseBinding.CommandProperty, binding);
        this.InputBindings.Add(mouseBinding);
    }
}

更新 4

BindingOperations.SetBinding 可用于无法直接访问 SetBinding 的对象。

解决方案

        MouseBinding mouseBinding = new MouseBinding();
        BindingOperations.SetBinding(mouseBinding, MouseBinding.CommandProperty, binding);
        this.InputBindings.Add(mouseBinding);

最佳答案

使用 ItemsControl为了这。当已经有一个内置类已经这样做时,不要试图自己破解一些东西。

您还可以使用 RelativeSource 从可视化树中的父 UI 元素访问 ViewModel绑定(bind):

<ItemsControl>
   <ItemsControl.ItemTemplate>
      <DataTemplate>
          <TextBlock Text="SomeText">
              <TextBlock.InputBindings>
                  <!-- See how I'm using RelativeSource to get a hold of the DataContext of the parent ItemsControl -->
                  <MouseBinding Command="{Binding DataContext.SomeCommandProperty,
                                                  RelativeSource={RelativeSource AncestorType=ItemsControl}}" 
                                MouseAction="LeftClick" />
              </TextBlock.InputBindings>
          </TextBlock>
      </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

关于c# - 有没有办法以编程方式绑定(bind)到 InputBinding Command 属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19669264/

相关文章:

c# - 从 MSBuild 3.5 而不是 Visual Studio 编译的类型推断失败 (CS0246)

c# - 快速视频显示 WPF

wpf - 如何在DataGridTextColumn的工具提示中显示IDataErrorInfo的错误?

c# - 通过使用带有 async/await 的 Linq 延迟执行而感到震惊

c# - WCF Web 服务中的安全上下文 token 无效或过期

c# - 如何使用滚动从 WPF DataGrid 中获取所有行

wpf - ScrollViewer 滚动条始终禁用

wpf - 绑定(bind)到集合中的单个元素

c# - 我如何使用 WPF 为 Google Chrome 之类的窗口设置主题?

c# - Nancy 并发请求同步运行