首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DataContext与ContentProperty的传递

DataContext与ContentProperty的传递
EN

Stack Overflow用户
提问于 2015-02-08 17:52:09
回答 2查看 110关注 0票数 2

我想创建一个自定义控件来简化以下代码:

代码语言:javascript
复制
<StackPanel>
    <DockPanel LastChildFill="True">
        <Label>First Name</Label>
        <TextBox Margin="2" Text="{Binding Path=FirstName}"></TextBox>
    </DockPanel>
    <DockPanel LastChildFill="True">
        <Label>Last Name</Label>
        <TextBox Margin="2" Text="{Binding Path=LastName}"></TextBox>
    </DockPanel>
</StackPanel>

我的想法是像下面这样制作一个UserControl (布局有点不同,但超出了范围):

代码语言:javascript
复制
<UserControl x:Class="LabelControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <DockPanel LastChildFill="True">
        <Label Content="{Binding Path=Text}" Margin="2" MinWidth="100" HorizontalContentAlignment="Right"></Label>
        <Grid Margin="2">
            <ContentControl Content="{Binding Path=Control}" ></ContentControl>
        </Grid>
    </DockPanel>
</UserControl>

后面的代码公开了两个依赖项属性:

  • 文本:标签的内容
  • 控件:要由内容承载的控件。该类使用ContentProperty属性将子级映射到ContentControl

这样我就可以简化我的StackPanel

代码语言:javascript
复制
<StackPanel>
    <controls:LabelControl Text="First Name">
        <TextBox Text="{Binding Path=FirstName}"></TextBox>
    </controls:LabelControl>
    <controls:LabelControl Text="Last Name">
        <TextBox Text="{Binding Path=LastName}"></TextBox>
    </controls:LabelControl>
</StackPanel>

我正在运行的问题是控件中的绑定不是映射。有办法绕过这件事吗?标签控件DataContext正在覆盖父控件上下文。

下面是LabelControl的代码:

代码语言:javascript
复制
[ContentProperty("Control")]
public partial class LabelControl : UserControl
{
    public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
        "Text", typeof(string), typeof(LabelControl), new PropertyMetadata(default(string)));

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    public static readonly DependencyProperty ControlProperty =
        DependencyProperty.Register("Control", typeof(Control), typeof(LabelControl), new PropertyMetadata(default(Control)));

    public Control Control
    {
        get { return (Control)GetValue(ControlProperty); }
        set { SetValue(ControlProperty, value); }
    }

    public LabelControl()
    {
        InitializeComponent();
        this.DataContext = this;
    }
}

编辑:输出确认数据文本正在重写。

代码语言:javascript
复制
BindingExpression path error: 'FirstName' property not found on 'object' ''LabelControl' (Name='')'. BindingExpression:Path=FirstName; DataItem='LabelControl' (Name=''); target element is 'TextBox' (Name=''); target property is 'Text' (type 'String')
EN

回答 2

Stack Overflow用户

发布于 2015-02-08 18:07:12

如果您的LabelControl包含在Window中,并且它的DataContext具有FirstName属性,请尝试像这样更改绑定。

代码语言:javascript
复制
<TextBox Text="{Binding Path=FirstName, 
                RelativeSource={RelativeSource AncestorType=Window}}">
</TextBox>

如果您不想每次指定RelativeSource,您可以像现在一样使用LabelControl .

代码语言:javascript
复制
<StackPanel>
    <controls:LabelControl Text="First Name">
        <TextBox Text="{Binding Path=FirstName}"></TextBox>
    </controls:LabelControl>
    <controls:LabelControl Text="Last Name">
        <TextBox Text="{Binding Path=LastName}"></TextBox>
    </controls:LabelControl>
</StackPanel>

...and将更改LabelControl的实现。

首先,从DataContext的代码背后释放LabelControl分配。

代码语言:javascript
复制
public LabelControl()
{
    InitializeComponent();
    //this.DataContext = this; // we don't want this
}

然后将XAML模板更改为

代码语言:javascript
复制
<DockPanel LastChildFill="True">
    <Label Content="{Binding Path=Text,
           RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}" 
           Margin="2" MinWidth="100" HorizontalContentAlignment="Right">
    </Label>
    <Grid Margin="2">
        <ContentControl 
            Content="{Binding Path=Control, 
            RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}">
        </ContentControl>
    </Grid>
</DockPanel>

现在您应该正确设置您的DataContext

票数 0
EN

Stack Overflow用户

发布于 2015-02-09 13:03:28

我发现使用UserControl不是最理想的解决方案。事实证明,模板化控件允许DataBinds在没有任何黑客(RelativeSource)的情况下通过。

代码语言:javascript
复制
[ContentProperty("Control")]
public class LabelControl : Control
{

    public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", 
        typeof(string), typeof(LabelControl), new PropertyMetadata(default(string)));

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    public static readonly DependencyProperty ControlProperty =
        DependencyProperty.Register("Control", typeof(Control), typeof(LabelControl), new PropertyMetadata(default(Control)));

    public Control Control
    {
        get { return (Control)GetValue(ControlProperty); }
        set { SetValue(ControlProperty, value); }
    }
}

在app.xaml中:

代码语言:javascript
复制
<Style TargetType="controls:LabelControl">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="controls:LabelControl">
                <DockPanel LastChildFill="True">
                    <Label Content="{TemplateBinding Text}"  MinWidth="100" FontSize="11"></Label>
                    <Grid Margin="2">
                        <ContentControl Content="{TemplateBinding Control}"></ContentControl>
                    </Grid>
                </DockPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28397267

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档