WPF DataContext ...寻找最简单的语法

时间:2010-09-09 03:19:01

标签: wpf xaml binding user-controls

在下面的XAML UserControl中,我将一些项绑定到UserControl的链接类中的属性。

<UserControl x:Class="Kiosk.EventSelectButton"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Kiosk"
    Height="130" Width="130">
    <Grid>
        <Button 
            Style="{DynamicResource DarkButton130x130}" 
            HorizontalAlignment="Left" 
            VerticalAlignment="Center">
            <Grid Margin="0,0,0,0" Height="118" Width="118">
                <Image VerticalAlignment="Top" HorizontalAlignment="Center" Source="image/select_button_arrows.png" />
                <Image x:Name="EventImageComponent" VerticalAlignment="Center" HorizontalAlignment="Center" Effect="{DynamicResource KioskStandardDropShadow}" Source="{Binding Path=EventImage}" />
                <TextBlock x:Name="SelectTextBlock" Text="{Binding Path=SelectText}" VerticalAlignment="Top" HorizontalAlignment="Center" Margin="0,-2,0,0" FontSize="10pt" Foreground="#5aaff5" />
                <TextBlock x:Name="LabelTextBlock" VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="0,0,0,0" FontSize="14pt" FontWeight="Bold" Text="{Binding Path=Label}"/>
            </Grid>
        </Button>
    </Grid>
</UserControl>

在链接类'contstructor中,我将项目的DataContext应用于 this ,如下所示。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Kiosk
{
    /// <summary>
    /// Interaction logic for EventSelectButton.xaml
    /// </summary>
    public partial class EventSelectButton : UserControl
    {

        public String ValueContainer;

        private String _EventImage;

        public String EventImage
        {
            get
            {
                return _EventImage;
            }
            set
            {
                _EventImage = value;
            }
        }

        private String _Label;

        public String Label
        {
            get
            {
                return _Label;
            }
            set
            {
                _Label = value;
            }
        }

        private String _SelectText;

        public String SelectText 
        {
            get 
            { 
                return _SelectText; 
            }
            set 
            { 
                _SelectText = value; 
            }
        }

        public EventSelectButton()
        {
            InitializeComponent();
            LabelTextBlock.DataContext = this;
            SelectTextBlock.DataContext = this;
            EventImageComponent.DataContext = this;
        }
    }
}

修改

虽然这是按预期工作的,但我很想知道是否有更简单的方法可以做到这一点。 (编辑,经验教训。)这实际上不会超出初始化,公共属性将被设置,但是因为类不使用DependentProperties或者实现INotifyPropertyChanged,绑定将不起作用正如所料。 (结束编辑

例如,

  • 我可以将XAML中这些项的DataContext设置为 this (作为EventSelectButton实例),如果是,如何?
  • 或者,是否可以从UserControl父级继承DataContext,从而使绑定路径更简单。

到目前为止,我发现的唯一替代品更加冗长,例如:使用RelativeSource绑定方法来定位EventSelectButton Ancestor。

所以,请让我知道我可以改进这种绑定表达式的任何方法,并且非常感谢任何关于在UserComponent中绑定的最佳实践的评论。

1 个答案:

答案 0 :(得分:2)

一种方法是执行以下操作:

  1. 在XAML中命名您的UserControl。
  2. 将根元素(即网格)的DataContext绑定到UserControl。
  3. 像这样:

    <UserControl x:Name="uc">
      <Grid DataContext="{Binding ElementName=uc}">
      .
      .
      .
      </Grid>
    </UserControl>
    

    现在,你会问,为什么不设置UserControl本身的DataContext?好吧,这只是确保设置UserControl实例的DataContext仍然可以工作,而不会影响UserControl的可视树中的绑定。所以像下面这样的东西仍然可以正常工作。

    <Window>
      <uc:EventSelectButton DataContext="{Binding SomeDataContext}" Width="{Binding SomeDataContextWidth}"/>
    </Window>
    

    修改

    要使解决方案完整,需要将UserControl中的属性更改为使用DependencyProperty对象。以下是代码的更新:

    XAML:

    <UserControl x:Class="Kiosk.EventSelectButton"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:Kiosk"
        x:Name="root"             
        Height="130" Width="130">
        <Grid x:Name="LayoutRoot" DataContext="{Binding ElementName=root}">
            <Button 
                Style="{DynamicResource DarkButton130x130}" 
                HorizontalAlignment="Left" 
                VerticalAlignment="Center">
                <Grid Margin="0,0,0,0" Height="118" Width="118" >
                    <Image VerticalAlignment="Top" HorizontalAlignment="Center" Source="image/select_button_arrows.png" />
                    <Image Source="{Binding EventImage}" VerticalAlignment="Center" HorizontalAlignment="Center" Effect="{DynamicResource KioskStandardDropShadow}"  />
                    <TextBlock Text="{Binding SelectText}" VerticalAlignment="Top" HorizontalAlignment="Center" Margin="0,-2,0,0" FontSize="10pt" Foreground="#5aaff5" />
                    <TextBlock Text="{Binding Label}" VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="0,0,0,0" FontSize="14pt" FontWeight="Bold" />
                </Grid>
            </Button>
        </Grid>
    </UserControl>
    

    代码隐藏:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace Kiosk
    {
        public partial class EventSelectButton : UserControl
        {
            public static readonly DependencyProperty EventImageProperty =
                    DependencyProperty.Register(
                    "EventImage",
                    typeof(string),
                    typeof(EventSelectButton));
    
            public String EventImage
            {
                get { return (string)GetValue(EventImageProperty); }
                set { SetValue(EventImageProperty, value); }
            }
    
            public static readonly DependencyProperty SelectTextProperty =
                    DependencyProperty.Register(
                    "SelectText",
                    typeof(string),
                    typeof(EventSelectButton));
    
            public String SelectText
            {
                get { return (string)GetValue(SelectTextProperty); }
                set { SetValue(SelectTextProperty, value); }
            }
    
            public static readonly DependencyProperty LabelProperty =
                    DependencyProperty.Register(
                    "Label",
                    typeof(string),
                    typeof(EventSelectButton));
    
            public String Label
            {
                get { return (string)GetValue(LabelProperty); }
                set { SetValue(LabelProperty, value); }
            }
    
            public EventSelectButton()
            {
                InitializeComponent();
            }
        }
    }