简体   繁体   English

如何将 datacontext 设置为 UserControl 的属性?

[英]How can I set the datacontext to property of a UserControl?

Having this structure and a combobox:具有此结构和 combobox:

public abstract class A: UserControl
{
     public string MachineName { get; protected set; }
     ...
}

public partial class MainWindow : Window
{
     private List<A> m_listA = new List<A>();

     public MainPanel()
     {
        InitializeComponent();
        DataContext = this;
     
        cbMachines.ItemsSource = m_listA;
        cbMachines.SelectedIndex = 0;
        cbMachines.DisplayMemberPath = "MachineName";
     }
}

If I execute it I have the list of elements of the combobox perfectly filled but the selected one is empty and throws a binding error:如果我执行它,我将完美填充 combobox 的元素列表,但所选元素为空并引发绑定错误:

System.Windows.Data Error: 40 : BindingExpression path error: 'Name' property not found on 'object' 
''Grid' (Name='')'. BindingExpression:Path=Name; DataItem='Grid' (Name=''); target element is 
'TextBlock' (Name=''); target property is 'Text' (type 'String')

It seems that, it takes the grid of "A" main control as datacontext it seems that, it takes the main control as data context, but i need the usercontrol as datacontext.看来,它将“A”主控件的网格作为数据上下文似乎将主控件作为数据上下文,但我需要用户控件作为数据上下文。

How can i do this?我怎样才能做到这一点?

The corresponding area in default ComboBox template is this:默认ComboBox模板中对应的区域是这样的:

<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" Content="{TemplateBinding SelectionBoxItem}" ContentStringFormat="{TemplateBinding SelectionBoxItemStringFormat}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" IsHitTestVisible="false" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>

In this visual, you cannot set SelectionBoxItemTemplate, SelectionBoxItem, SelectionBoxItemStringFormat because they are read only .在此视觉效果中,您无法设置 SelectionBoxItemTemplate、SelectionBoxItem、SelectionBoxItemStringFormat,因为它们是只读的。

According to .NET Source code (Combobox.cs UpdateSelectionBoxItem method) it checks if current item is ContentControl.根据.NET 源代码(Combobox.cs UpdateSelectionBoxItem 方法)检查当前项目是否为 ContentControl。 If so, it gets Content as SelectionBoxItem;如果是,则将 Content 作为 SelectionBoxItem; ContentTemplate as SelectionBoxItemTemplate and ContentStringFormat as SelectionBoxItemStringFormat. ContentTemplate 作为 SelectionBoxItemTemplate 和 ContentStringFormat 作为 SelectionBoxItemStringFormat。

As UserControl derives from ContentControl;由于 UserControl 派生自 ContentControl; you can make it possible by setting ContentTemplate for class A like this:您可以通过为 class A 设置 ContentTemplate 来实现,如下所示:

<UserControl.ContentTemplate>
    <DataTemplate>
        <TextBlock Text="{Binding Parent.MachineName}" />
    </DataTemplate>
</UserControl.ContentTemplate>

Or you can use a custom template for ComboBox to assign content like this:或者您可以使用 ComboBox 的自定义模板来分配如下内容:

Content="{Binding SelectedItem.MachineName, RelativeSource={RelativeSource Mode=TemplatedParent}}"

To get the default combobox template use this .要获取默认 combobox 模板,请使用此.

Or you can do it on code behind:或者你可以在后面的代码上做到这一点:

cbMachines.ApplyTemplate();
var contentPresenter = cbMachines.Template.FindName("contentPresenter", cbMachines) as ContentPresenter;
System.Windows.Data.BindingOperations.SetBinding(contentPresenter, ContentPresenter.ContentProperty, new Binding("SelectedItem.MachineName") { Source = cbMachines });
contentPresenter.ContentTemplateSelector = null;

There is no easier way, I'm afraid.恐怕没有更简单的方法了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM