【问题标题】:WPF DataContext ... looking for the simplest syntaxWPF DataContext ...寻找最简单的语法
【发布时间】:2011-04-10 01:36:51
【问题描述】:

在下面的 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>

在链接类的构造函数中,我将项目的 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 中绑定的最佳实践的 cmets。

【问题讨论】:

    标签: wpf xaml binding user-controls


    【解决方案1】:

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

    1. 在 XAML 中命名您的 UserControl。
    2. 将根元素(即 Grid)的 DataContext 绑定到 UserControl。

    像这样:

    <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();
            }
        }
    }
    

    【讨论】:

    • 这很有趣,我在发布问题之前尝试了 ElementName 绑定表达式,但它们不起作用。例如
    • 但我认为设置父母的 DataContext 应该由它的孩子继承?
    • 是的。如果在 Grid 上设置 DataContext,则其中的每个元素都将继承该 DataContext。您还想在上面的代码中做的一件事是 a) 将 UserControl 的属性更改为 DependencyProperty 对象(推荐)或 b) 在 UserControl 上实现 INotifyPropertyChanged,在属性设置器上引发 PropertyChanged 事件。跨度>
    • 顺便说一句,当您尝试 ElementName 时,究竟是什么不起作用?你有没有得到任何错误?还是绑定似乎不起作用?如果是后者,请尝试将我建议的更改合并到 UserControl 的属性中。我最初的怀疑是它与 PropertyChanged 通知有关。
    • 好吧,如果你不使用依赖属性,是的,它会有点“崩溃”。每当 UserControl 属性设置为新值时,您的绑定都不会收到通知。因此,例如,如果您有一个在某处设置 myUserControl.SelectText="New Text" 的按钮,则实际属性将得到更新,但与此绑定的 不会得到更新。使用依赖属性可以解决这个问题。正如我上面所建议的,另一种方法是实现 INotifyPropertyChanged。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-19
    • 1970-01-01
    相关资源
    最近更新 更多