绑定UserControls的元素

时间:2013-05-26 00:38:00

标签: c# wpf binding user-controls

我创建了一个名为SimpleText的UserControls,并在我的MainWindow.xaml中引用它。我的SimpleText中唯一的东西是TextBox(称为tbox)。在我的MainWindow中有另一个TextBox(称为tbox2)。我想要实现的是在两个文本框之间使用TwoWay绑定。

我在stackoverflow中读到,为了在内部更改内容,你必须在UserControls的代码中声明一个属性(如果不需要,请纠正我):

 public string MyText
        {
            get { return tboxUser.Text; }
            set { tboxUser.Text = value; }
        }

然后我可以从MainWindow.xaml访问MyText,但只能给它“静态”值:

Window x:Class="WpfApplication11.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication11"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <!-- <local:SimpleText MyText="Hello"/>  Works !-->
        <local:SimpleText MyText="{Binding Text, ElementName=tbox2}"/> <!--Does not work-->
        <TextBox x:Name="tbox2" Margin="0,200,0,0"  Text="Text Box 2" />
    </Grid>
</Window>

这给我一个错误说:

无法在'SimpleText'类型的'MyText'属性上设置'绑定'。 '绑定'只能在DependencyObject的DependencyProperty上设置。

但遗憾的是我在这里非常新手,我不知道如何让MyText成为DependencyProperty。感谢。

1 个答案:

答案 0 :(得分:2)

ripped from http://www.andrewdenhertog.com/c/create-dependencyproperty-dependencyobject-5-minutes/

public int Age
    {
        get { return (int)GetValue(AgeProperty); } //do NOT modify anything in here
        set { SetValue(AgeProperty, value); } //...or here
    }

    // Using a DependencyProperty as the backing store for Age.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty AgeProperty =
        DependencyProperty.Register(
        "Age",  //Must be the same name as the property created above
        typeof(int), //Must be the same type as the property created above
        typeof(Person), //Must be the same as the owner class
        new UIPropertyMetadata(
            0,  //default value, must be of the same type as the property
            new PropertyChangedCallback((s, e) =>  //A callback that gets executed when the property changed
            {
                var source = s as Person;
                s.DOB_Year = DateTime.Now.Year - s.Age; 
            })));

对于您的情况,它将类似于下面(请注意frameworkpropertymetadataoptions.bindstwowaybydefault)。我没有真正测试过这个,所以不确定语法是否合适,但它的一般想法

public string MyText
{
    get { return (string)GetValue(MyTextProperty); } //do NOT modify anything in here
    set { SetValue(MyTextProperty, value); }
}

public static readonly DependencyProperty MyTextProperty = DependencyProperty.Register("MyText", typeof(string), typeof(SimpleText), new FrameworkPropertyMetadata(null,
                              FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                              MyTextPropertyChangedCallback));

private static void MyTextPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var source = d as SimpleText;
    source.MyText = e.NewValue.ToString();
}

<强>更新

我尝试使用这个简单的示例重新创建并注意到您在评论中的相同内容。 This article提供了更深入的解释。在本文的底部,它描述了如何从父级继承用户控件的数据上下文。您不会在编译时看到错误,但如果您turn on wpf tracing for data binding,您会注意到输出控制台中的数据绑定错误。修复是调整用户控件中的数据上下文,这可以通过几种方式完成,但最简单的可能是在构造函数中,将数据上下文设置在xaml(网格或堆栈面板或其他任何位置)的顶级UI元素中)对自己。

public SimpleText()
{
    InitializeComponent();
    grid.DataContext = this;
}