有没有办法以编程方式绑定到输入绑定命令属性
本文关键字:绑定 输入 命令 属性 方式 编程 有没有 | 更新日期: 2023-09-27 18:37:26
我知道这是一个通用标题,但我的问题很具体。 我认为这将归结为实践问题。 所以,我有以下代码:
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 类中,但我目前正在放弃该选项,假设有另一种方法。
组件是 ComponentCollection 的子级,ComponentCollection 是 DataContext 是 MyViewModel 的网格的子级。顾名思义,组件集合包含组件的集合。
<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
基本上,我有一个自定义控件,它从面板继承哪些子项是组件的集合。 这不是一个黑客,就像我提到的,如果我将ViewModel聚合到组件中,我可以直接访问SomeCommandProperty。 然而,这样做感觉很恶心。 也就是说,可以从模型直接访问视图模型。
我想我要问的问题是。鉴于组件的父UIElement的DataContext设置为MyViewModel的情况,是否可以访问SomeCommandProperty,而无需组件拥有对拥有SomeCommandProperty的MyViewModel的引用?从编程上讲,就是这样。
使用 ItemsControl 不会改变我仍然需要将 SomeCommandProperty 绑定到每个 Items 的事实。
更新 2
请参阅上面的代码。
更新 3
显然,据我所知,没有一种机制可以在 InputBinding 的 Command 属性上设置绑定。
例如,如果我的组件类要从ButtonBase继承而不是UIElement,我将拥有Command属性,我可以使用FrameWorkElement的SetBinding轻松地以编程方式设置绑定。 不幸的是,我无法使用 InputBinding 的 Command 属性执行此操作。
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:
<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>