将Silverlight UserControl自定义属性绑定到其元素

Ron*_*īts 17 data-binding silverlight user-controls silverlight-2.0

我正在尝试在Silverlight 2.0中制作一个简单的填字游戏.我正在研究一个UserControl-ish组件,它代表了拼图中的一个正方形.我将UserControl的属性与其元素绑定在一起时遇到了麻烦.我终于(有点)让它工作了(可能对某些人有所帮助 - 它花了我几个小时),但是想让它更"优雅".

我想象它应该有内容的隔间和标签(在右上角),可选地包含它的'数字.内容控件可能是TextBox,而标签控件可能是TextBlock.所以我用这个基本结构创建了一个UserControl(这个值在这个阶段是硬编码的):

    <UserControl x:Class="XWord.Square"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    FontSize="30" 
    Width="100" Height="100">
        <Grid x:Name="LayoutRoot" Background="White">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>

            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>

            <TextBlock x:Name="Label" Grid.Row="0" Grid.Column="1" 
                Text="7"/>
            <TextBox x:Name="Content" Grid.Row="1" Grid.Column="0"  
                Text="A"
                BorderThickness="0" />

        </Grid>
    </UserControl>
Run Code Online (Sandbox Code Playgroud)

我也在Square类中创建了DependencyProperties,如下所示:

     public static readonly DependencyProperty LabelTextProperty;
     public static readonly DependencyProperty ContentCharacterProperty;

     // ...(static constructor with property registration, .NET properties
     // omitted for brevity)...
Run Code Online (Sandbox Code Playgroud)

现在我想弄清楚如何将Label和Content元素绑定到两个属性.我是这样做的(在代码隐藏文件中):

     Label.SetBinding( TextBlock.TextProperty, new Binding { Source = this, Path = new PropertyPath( "LabelText" ), Mode = BindingMode.OneWay } );
     Content.SetBinding( TextBox.TextProperty, new Binding { Source = this, Path = new PropertyPath( "ContentCharacter" ), Mode = BindingMode.TwoWay } );
Run Code Online (Sandbox Code Playgroud)

这在XAML中会更优雅.有谁知道这是怎么做的?

lo5*_*lo5 19

首先,使用{RelativeSource Self}在UserControl上设置DataContext:

<UserControl x:Class="XWord.Square"  
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"   
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
FontSize="30"   
Width="100" Height="100" 
DataContext="{Binding RelativeSource={RelativeSource Self}}">
Run Code Online (Sandbox Code Playgroud)

现在,您可以将各个元素绑定到usercontrol的属性:

<TextBlock x:Name="Label" Grid.Row="0" Grid.Column="1" 
Text="{Binding LabelText}"/>  
<TextBox x:Name="Content" Grid.Row="1" Grid.Column="0" 
Text="{Binding ContentCharacter}" BorderThickness="0" />
Run Code Online (Sandbox Code Playgroud)

对于SL 2.0,您需要在UserControl的Loaded事件处理程序上设置DataContext.

private void UserControl_Loaded( object sender, RoutedEventArgs e ) {
    LayoutRoot.DataContext = this;
}
Run Code Online (Sandbox Code Playgroud)


jms*_*era 7

由于Silverlight无法使用FindAncestor技术,您可以使用类似于设置UserControl名称的技巧,但不会通过使用LayoutRoot的名称来破坏其功能...

<UserControl x:Class="XWord.Square"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
FontSize="30" 
Width="100" Height="100">
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <TextBlock x:Name="{Binding Path=Parent.LabelText, ElementName=LayoutRoot}" Grid.Row="0" Grid.Column="1" 
            Text="7"/>
        <TextBox x:Name="{Binding Path=Parent.ContentCharacter, ElementName=LayoutRoot}" Grid.Row="1" Grid.Column="0"  
            Text="A"
            BorderThickness="0" />
    </Grid>
</UserControl>
Run Code Online (Sandbox Code Playgroud)

它在SL3中工作,无需添加任何额外的代码(我在WP7应用程序中使用它),但不知道你是否可以在SL2中使用它.好吧,我现在意识到这个问题是如何陈旧的,希望它仍然有用,我来到这里是因为我在WP7中遇到同样问题的答案并没有让我信服.


小智 1

我可能不太清楚你的问题。在 Silverlight 中,您可以绑定到几乎任何数据对象。因此,如果您有一个包含 Content 和 Label 属性的 PuzzleSquare 类,您可以直接从对象绑定到这些属性。

假设您创建了一个简单的对象 PuzzleSquare:

    public class PuzzleSquare
    {
      public string Content{ get; set; }
      public string Label{ get; set; }

      public void PuzzleSquare(){};
      public void PuzzleSquare(string label, string content):this()
      {
         Content = content;
         Label = label;
      }    
    }
Run Code Online (Sandbox Code Playgroud)

因此,如果您使用经典视图/隐藏代码模型构建应用程序,则隐藏代码会在页面加载时将此对象添加到网格的 DataContext 属性中:

LayoutRoot.DataContext = new PuzzleSquare("1", "A");
Run Code Online (Sandbox Code Playgroud)

您的 Xaml 将绑定到 Square 属性:

    <TextBlock x:Name="Label" Grid.Row="0" Grid.Column="1" 
Text="{Binding Label}"/>            
    <TextBox x:Name="Content" Grid.Row="1" Grid.Column="0" 
Text="{Binding Content}" BorderThickness="0" />
Run Code Online (Sandbox Code Playgroud)

那有意义吗?

ib.