【问题标题】:Silverlight 3 user control data Binding in xamlSilverlight 3 用户控件数据在 xaml 中的绑定
【发布时间】:2010-11-18 02:11:48
【问题描述】:

我正在尝试实现一些概念上非常简单但似乎无法让它发挥作用的东西。

我有一个名为 c1 的类,它有 2 个依赖属性,一个整数 I 和一个字符串 S。它实现了 INotifiyPropertyChanged。

public class c1: INotifyPropertyChanged 
{
    private int i;
    public int I { get { return i; } set { i = value; if(PropertyChanged != null) PropertyChanged(this,new PropertyChangedEventArgs("I")); } }
    private string s;
    public string S { get { return s; } set { s = value; if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("S")); } }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion
}

此类由 Silverlight 用户控件 SUC 引用,该控件还实现 INotifiyPropertyChanged 作为依赖属性 C,具有 PropertyChangedCallback 等。如下所示。

public partial class SUC : UserControl, INotifyPropertyChanged
{

    public c1 C
    {
        get { return (c1)GetValue(CProperty); }
        set { SetValue(CProperty, value); }
    }
    public static readonly DependencyProperty CProperty =
        DependencyProperty.Register("C", typeof(c1), typeof(SUC), new PropertyMetadata(new c1(), new PropertyChangedCallback(c1Changed)));


    private static void c1Changed(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        SUC s = obj as SUC;
        if (s != null)
            s.CChanged((c1)e.NewValue);
    }

    public void CChanged(c1 c)
    {
        C = c;
        if(PropertyChanged!=null)
            PropertyChanged(this,new PropertyChangedEventArgs("C"));
    }
    public SUC()
    {
        InitializeComponent();
        this.DataContext = this;
    }

    private void bclick(object sender, RoutedEventArgs e)
    {
        C.S = C.S + " Clicked";
        MessageBox.Show(C.I.ToString() + " - " + C.S);
    }
    public event PropertyChangedEventHandler PropertyChanged;
}

在我也实现 INotifiyPropertyChanged 的​​主页中,我有一个 c1 和 SUC 的实例。

public partial class MainPage : UserControl, INotifyPropertyChanged
{


    public c1 MC
    {
        get { return (c1)GetValue(MCProperty); }
        set { SetValue(MCProperty, value); }
    }

    public static readonly DependencyProperty MCProperty =
        DependencyProperty.Register("MC", typeof(c1), typeof(MainPage), new PropertyMetadata(new c1()));


    private static void MCChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        MainPage mp = d as MainPage;
        if (mp != null)
            mp.MCChanged();
    }

    public void MCChanged()
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs("MC"));
    }

    public MainPage()
    {
        InitializeComponent();
        MC.S = "ssss";
        this.DataContext = this;
    }


    public event PropertyChangedEventHandler PropertyChanged;

}

我想通过 XAML 设置 SUC 用户控件的 C 属性。像这样

local:SUC x:Name="suc" C="{Binding MC, Mode=TwoWay}"

这在后面的 c# 代码中运行良好,但在 XAML 中却不行。我在 XAML 中需要它的原因是因为我想将 c1 的集合绑定到 DataTemplate 中的 SUC。

任何带有可下载代码的工作示例将不胜感激。

【问题讨论】:

    标签: silverlight data-binding user-controls


    【解决方案1】:

    这是SUC类的构造函数中的一个简单的小bug:

        public SUC()
        {
            InitializeComponent();
            this.DataContext = this; //this line shouldn't be here, delete and it will work
        }
    

    这意味着 SUC 控件的 DataContext 本身而不是 MainPage 类,这是它绑定到 MainPage.MC 所需要的(SUC 类没有 MC 属性)。

    另外,我知道其中大部分是您可能只是想让它工作,但 MC 不需要是 DP,您不需要“C=c;”在 SUC 中的行,我也不会将 MainPage 控件类用作数据上下文类,创建另一个类来将 DataContext 绑定到。

    【讨论】:

    • 感谢您的回复马特曼瑟。我不明白为什么 UserControl 不能从它正在使用的页面中拥有一个单独的 DataContext 。我只需要主页和用户控件来共享一个变量,然后它们是 2 个独立的实体。我想为 Page 和 UserControl 使用一个公共类作为 DataContext 是一个可行的选择(尽管它感觉像是一种妥协)。
    • 这就是它应该如何工作的。控件是 UI 元素,而不是业务对象。您应该将控件绑定到单独的业务对象。在此处查看 MVC/MVVM 模式和 MS 对数据绑定的解释:silverlight.net/learn/tutorials/databinding.aspx
    【解决方案2】:

    问题似乎是您在加载 XAML 之后设置了 DataContextUserControl。在加载 XAML 之前设置它(即在 InitializeComponent 之前),或者更好的是,在 XAML 中设置它:

    <local:MainPage ... DataContext="{Binding RelativeSource={RelativeSource Self}}">
        ....
    </local:MainPage>
    

    RelativeSource 绑定指定你的MainPageDataContext 应该是它自己,这似乎是你想要的。这样就消除了代码隐藏中DataContext 的分配,这在 WPF/Silverlight 中总是一件好事。

    希望对您有所帮助。

    【讨论】:

    • 感谢您的回复诺多林。事实证明,在 InitializeComponent 之前设置 DataContext 会导致在调用 InitializeComponent 之后将 DataContext 设置为 MainPage 的 DataContext。这里的问题是(正如 mattmanser 下面提到的)用户控件的 DataContext 最终没有 C 属性并且没有在 XAML 中绑定到它。
    【解决方案3】:

    用户控件的控件的数据上下文可以不同于用户控件本身或用户控件的父“窗体”(或父页面,用户控件)。您必须在后面的代码中设置绑定。有关更多信息,请参阅此帖子:Silverlight UserControl Custom Property Binding

    另外,您可能想要创建 Silverlight Control 而不是 Silverlight UserControl

    【讨论】:

      猜你喜欢
      • 2013-03-30
      • 1970-01-01
      • 2023-03-24
      • 1970-01-01
      • 2016-01-12
      • 1970-01-01
      • 1970-01-01
      • 2010-12-20
      • 2011-02-03
      相关资源
      最近更新 更多