如何将 UserControl 绑定到自定义控件的内容
How to bind UserControl to content of custom control
我正在尝试创建一个非常灵活的自定义控件。我正在尝试实现的灵活性,以便能够将 UserControl
绑定到 ExpanderContent
Dependency
属性,代码片段后面:
public partial class ChartBar : UserControl
{
public UIElement ExpanderContent
{
get { return (UIElement)GetValue(ExpanderContentProperty); }
set { SetValue(ExpanderContentProperty, value); }
}
// Using a DependencyProperty as the backing store for ExpanderContent. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ExpanderContentProperty =
DependencyProperty.Register("ExpanderContent", typeof(UIElement), typeof(ChartBar), new PropertyMetadata(null, OnExpanderContentChanged));
private static void OnExpanderContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
//throw new NotImplementedException();
}
.
.
.
我试过在 XAML 中使用 ContentPresenter
但它不起作用。我显然可以填充按钮并且它可以工作,但这会通过绑定破坏动态内容。
<Expander x:Name="expander" Header="" VerticalAlignment="Top" d:LayoutOverrides="Width" Style="{DynamicResource ExpanderStyle1}">
<ContentPresenter Content="{Binding ExpanderContent, ElementName=TestControlWithContent}" />
<!--<WrapPanel HorizontalAlignment="Center" >
<Button Content="A" Style="{DynamicResource ButtonStyle1}" />
<Button Content="B" Style="{DynamicResource ButtonStyle1}" />
<Button Content="C" Style="{DynamicResource ButtonStyle1}" />
<Button Content="D" Style="{DynamicResource ButtonStyle1}" />
<Button Content="E" Style="{DynamicResource ButtonStyle1}" />
<Button Content="F" Style="{DynamicResource ButtonStyle1}" />
</WrapPanel>-->
</Expander>
更迷茫的是我能做到
// ChartBarParent is the name of the custom control set in XAML
ChartBarParent.Content = new TestControlWithContent();
它的工作原理以及触发回调。
最终,UIElement
在依赖项 属性 中并使用 ContentPresenter
是正确的方法吗?
尝试将 ContentPresenter 更改为 ContentControl。
此外,您可以将 UserControl 包装在 DataTemplate 中并将其设置为 ContentControl.ContentTemplate 允许您通过 ContentControl.Content 属性.
流动数据上下文
以下是我的操作方法。它依赖于 SecondaryContent
要么是 UI 东西(就像下面 "Usage" 中的第二个例子),要么是一个带有隐式 DataTemplate
的视图模型。我可以很容易地添加一个 SecondaryDataTemplateSelector
属性 来让消费者更明确地控制模板是如何发生的。
ChartBar.cs
public class ChartBar : ContentControl
{
static ChartBar()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ChartBar),
new FrameworkPropertyMetadata(typeof(ChartBar)));
}
// Rather than ExpanderContent, we're inheriting ContentControl.Content for the
// main control content.
#region SecondaryContent Property
public Object SecondaryContent
{
get { return (Object)GetValue(SecondaryContentProperty); }
set { SetValue(SecondaryContentProperty, value); }
}
public static readonly DependencyProperty SecondaryContentProperty =
DependencyProperty.Register("SecondaryContent", typeof(Object), typeof(ChartBar),
new PropertyMetadata(null));
#endregion SecondaryContent Property
#region IsExpanded Property
// This is optional. I just know I'd end up wanting it.
public bool IsExpanded
{
get { return (bool)GetValue(IsExpandedProperty); }
set { SetValue(IsExpandedProperty, value); }
}
public static readonly DependencyProperty IsExpandedProperty =
DependencyProperty.Register("IsExpanded", typeof(bool), typeof(ChartBar),
new PropertyMetadata(false));
#endregion IsExpanded Property
}
Themes/Generic.xaml
,或者 App.xaml,在 <Application.Resources>
内,或者其他一些。xaml 包含在一个或另一个中的资源字典。
<ControlTemplate x:Key="ChartBarDefaultTemplate" TargetType="local:ChartBar">
<!--
Use Binding/RelativeSource TemplatedParent on IsExpanded so it updates both ways,
or remove that attribute/binding if you're not bothering with the IsExpanded DP.
-->
<Expander
x:Name="expander"
Header=""
VerticalAlignment="Top"
Style="{DynamicResource ExpanderStyle1}"
IsExpanded="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}"
>
<StackPanel Orientation="Vertical">
<ContentPresenter />
<ContentControl
Content="{TemplateBinding SecondaryContent}"
/>
</StackPanel>
</Expander>
</ControlTemplate>
<Style TargetType="local:ChartBar">
<Setter
Property="Template"
Value="{StaticResource ChartBarDefaultTemplate}"
/>
</Style>
用法:
<StackPanel Orientation="Vertical" >
<!-- Control content -->
<local:ChartBar SecondaryContent="Secondary Content One">
<StackPanel Orientation="Vertical">
<Label>Chart Bar</Label>
<Ellipse Height="30" Width="60" Fill="GreenYellow" Opacity="0.2" />
<Label>Other stuff, etc. etc.</Label>
</StackPanel>
</local:ChartBar>
<!-- Templated viewmodel content -->
<local:ChartBar Content="{Binding RandomViewModelProperty}" IsExpanded="True">
<local:ChartBar.ContentTemplate>
<DataTemplate>
<Label Background="Beige" Content="{Binding}" Margin="20" />
</DataTemplate>
</local:ChartBar.ContentTemplate>
<local:ChartBar.SecondaryContent>
<ComboBox>
<TextBlock Text="One" />
<TextBlock Text="Two" />
<TextBlock Text="Three" />
</ComboBox>
</local:ChartBar.SecondaryContent>
</local:ChartBar>
</StackPanel>
我正在尝试创建一个非常灵活的自定义控件。我正在尝试实现的灵活性,以便能够将 UserControl
绑定到 ExpanderContent
Dependency
属性,代码片段后面:
public partial class ChartBar : UserControl
{
public UIElement ExpanderContent
{
get { return (UIElement)GetValue(ExpanderContentProperty); }
set { SetValue(ExpanderContentProperty, value); }
}
// Using a DependencyProperty as the backing store for ExpanderContent. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ExpanderContentProperty =
DependencyProperty.Register("ExpanderContent", typeof(UIElement), typeof(ChartBar), new PropertyMetadata(null, OnExpanderContentChanged));
private static void OnExpanderContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
//throw new NotImplementedException();
}
.
.
.
我试过在 XAML 中使用 ContentPresenter
但它不起作用。我显然可以填充按钮并且它可以工作,但这会通过绑定破坏动态内容。
<Expander x:Name="expander" Header="" VerticalAlignment="Top" d:LayoutOverrides="Width" Style="{DynamicResource ExpanderStyle1}">
<ContentPresenter Content="{Binding ExpanderContent, ElementName=TestControlWithContent}" />
<!--<WrapPanel HorizontalAlignment="Center" >
<Button Content="A" Style="{DynamicResource ButtonStyle1}" />
<Button Content="B" Style="{DynamicResource ButtonStyle1}" />
<Button Content="C" Style="{DynamicResource ButtonStyle1}" />
<Button Content="D" Style="{DynamicResource ButtonStyle1}" />
<Button Content="E" Style="{DynamicResource ButtonStyle1}" />
<Button Content="F" Style="{DynamicResource ButtonStyle1}" />
</WrapPanel>-->
</Expander>
更迷茫的是我能做到
// ChartBarParent is the name of the custom control set in XAML
ChartBarParent.Content = new TestControlWithContent();
它的工作原理以及触发回调。
最终,UIElement
在依赖项 属性 中并使用 ContentPresenter
是正确的方法吗?
尝试将 ContentPresenter 更改为 ContentControl。
此外,您可以将 UserControl 包装在 DataTemplate 中并将其设置为 ContentControl.ContentTemplate 允许您通过 ContentControl.Content 属性.
流动数据上下文以下是我的操作方法。它依赖于 SecondaryContent
要么是 UI 东西(就像下面 "Usage" 中的第二个例子),要么是一个带有隐式 DataTemplate
的视图模型。我可以很容易地添加一个 SecondaryDataTemplateSelector
属性 来让消费者更明确地控制模板是如何发生的。
ChartBar.cs
public class ChartBar : ContentControl
{
static ChartBar()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ChartBar),
new FrameworkPropertyMetadata(typeof(ChartBar)));
}
// Rather than ExpanderContent, we're inheriting ContentControl.Content for the
// main control content.
#region SecondaryContent Property
public Object SecondaryContent
{
get { return (Object)GetValue(SecondaryContentProperty); }
set { SetValue(SecondaryContentProperty, value); }
}
public static readonly DependencyProperty SecondaryContentProperty =
DependencyProperty.Register("SecondaryContent", typeof(Object), typeof(ChartBar),
new PropertyMetadata(null));
#endregion SecondaryContent Property
#region IsExpanded Property
// This is optional. I just know I'd end up wanting it.
public bool IsExpanded
{
get { return (bool)GetValue(IsExpandedProperty); }
set { SetValue(IsExpandedProperty, value); }
}
public static readonly DependencyProperty IsExpandedProperty =
DependencyProperty.Register("IsExpanded", typeof(bool), typeof(ChartBar),
new PropertyMetadata(false));
#endregion IsExpanded Property
}
Themes/Generic.xaml
,或者 App.xaml,在 <Application.Resources>
内,或者其他一些。xaml 包含在一个或另一个中的资源字典。
<ControlTemplate x:Key="ChartBarDefaultTemplate" TargetType="local:ChartBar">
<!--
Use Binding/RelativeSource TemplatedParent on IsExpanded so it updates both ways,
or remove that attribute/binding if you're not bothering with the IsExpanded DP.
-->
<Expander
x:Name="expander"
Header=""
VerticalAlignment="Top"
Style="{DynamicResource ExpanderStyle1}"
IsExpanded="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}"
>
<StackPanel Orientation="Vertical">
<ContentPresenter />
<ContentControl
Content="{TemplateBinding SecondaryContent}"
/>
</StackPanel>
</Expander>
</ControlTemplate>
<Style TargetType="local:ChartBar">
<Setter
Property="Template"
Value="{StaticResource ChartBarDefaultTemplate}"
/>
</Style>
用法:
<StackPanel Orientation="Vertical" >
<!-- Control content -->
<local:ChartBar SecondaryContent="Secondary Content One">
<StackPanel Orientation="Vertical">
<Label>Chart Bar</Label>
<Ellipse Height="30" Width="60" Fill="GreenYellow" Opacity="0.2" />
<Label>Other stuff, etc. etc.</Label>
</StackPanel>
</local:ChartBar>
<!-- Templated viewmodel content -->
<local:ChartBar Content="{Binding RandomViewModelProperty}" IsExpanded="True">
<local:ChartBar.ContentTemplate>
<DataTemplate>
<Label Background="Beige" Content="{Binding}" Margin="20" />
</DataTemplate>
</local:ChartBar.ContentTemplate>
<local:ChartBar.SecondaryContent>
<ComboBox>
<TextBlock Text="One" />
<TextBlock Text="Two" />
<TextBlock Text="Three" />
</ComboBox>
</local:ChartBar.SecondaryContent>
</local:ChartBar>
</StackPanel>