如何将数据上下文设置为 UserControl 的 属性?
How can I set the datacontext to property of a UserControl?
具有此结构和组合框:
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";
}
}
如果我执行它,我会得到完美填充的组合框元素列表,但所选元素为空并引发绑定错误:
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')
好像是以“A”主控的grid作为datacontext
看来,它把主控件作为数据上下文,但我需要用户控件作为数据上下文。
我该怎么做?
默认的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}"/>
在此视觉对象中,您无法设置 SelectionBoxItemTemplate、SelectionBoxItem、SelectionBoxItemStringFormat,因为它们只读。
根据 .NET Source code(Combobox.cs UpdateSelectionBoxItem 方法),它检查当前项目是否为 ContentControl。如果是这样,它将 Content 作为 SelectionBoxItem; ContentTemplate 作为 SelectionBoxItemTemplate,ContentStringFormat 作为 SelectionBoxItemStringFormat。
由于 UserControl 派生自 ContentControl;您可以通过为 class A 设置 ContentTemplate 来实现,如下所示:
<UserControl.ContentTemplate>
<DataTemplate>
<TextBlock Text="{Binding Parent.MachineName}" />
</DataTemplate>
</UserControl.ContentTemplate>
或者您可以使用 ComboBox 的自定义模板来分配如下内容:
Content="{Binding SelectedItem.MachineName, RelativeSource={RelativeSource Mode=TemplatedParent}}"
获取默认的组合框模板use this。
或者您可以在后面的代码中完成:
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;
恐怕没有更简单的方法了。
具有此结构和组合框:
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";
}
}
如果我执行它,我会得到完美填充的组合框元素列表,但所选元素为空并引发绑定错误:
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')
好像是以“A”主控的grid作为datacontext 看来,它把主控件作为数据上下文,但我需要用户控件作为数据上下文。
我该怎么做?
默认的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}"/>
在此视觉对象中,您无法设置 SelectionBoxItemTemplate、SelectionBoxItem、SelectionBoxItemStringFormat,因为它们只读。
根据 .NET Source code(Combobox.cs UpdateSelectionBoxItem 方法),它检查当前项目是否为 ContentControl。如果是这样,它将 Content 作为 SelectionBoxItem; ContentTemplate 作为 SelectionBoxItemTemplate,ContentStringFormat 作为 SelectionBoxItemStringFormat。
由于 UserControl 派生自 ContentControl;您可以通过为 class A 设置 ContentTemplate 来实现,如下所示:
<UserControl.ContentTemplate>
<DataTemplate>
<TextBlock Text="{Binding Parent.MachineName}" />
</DataTemplate>
</UserControl.ContentTemplate>
或者您可以使用 ComboBox 的自定义模板来分配如下内容:
Content="{Binding SelectedItem.MachineName, RelativeSource={RelativeSource Mode=TemplatedParent}}"
获取默认的组合框模板use this。
或者您可以在后面的代码中完成:
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;
恐怕没有更简单的方法了。