2010-07-09 114 views
1

问候乡亲们! 我遇到了一个WPF数据绑定问题,我希望你能帮忙。我是新来的WPF,但一个expereienced开发人员(VB 3.0-6.0,C#)。XAML内联数据绑定不起作用;绑定作品背后的代码

这里是场景: 我有一个名为MasterPartsData的C#项目,其中包含了许多不同类型的部件(电容器,二极管等)的类。它们从一个名为clsPart的基类继承而来。我有另一个C#WPF项目,其中包含WPF UserControls(以及一个MainWindow),以直观地表示存储在一个单独的MasterPartsData(MPD)对象中的值。我在usercontrol中创建了一个私有字段,用getter和setter来保存对象。

如果我创建在设定器的结合显式填充的对象:

_capacitor = value; 
Binding binding = new Binding(); 
binding.Source = _capacitor; 
binding.Path = new PropertyPath("C0uf"); 
this.txtC0uf.SetBinding(TextBox.TextProperty, binding); 

(与_capacitor作为私有对象变量和C0uf为属性名) 值正确显示。

但是我不希望在后面的代码中明确创建每个绑定。我的首选是在XAML中内联创建绑定,也许使用指向该对象的DataContext。

不幸的是,我试过的每一个不同的排列都失败了;该文本框不显示数据。

我有几个怀疑: 1)绑定是正确的,但文本框需要刷新。 2)绑定混淆了私有变量和属性。 3)也许类在不同的项目中定义的事实是造成问题。 4)我生气了,应该在有人受伤前检查自己进入庇护所。 :)

任何帮助,您可以提供将不胜感激。我非常乐意添加更多信息,但并不希望将问题与页面和源代码页面混淆起来。

回答

4

对于您的怀疑:

1)我认为TextBox的默认绑定行为是TwoWay,具有LostFocus更新触发,这意味着你的UI重点将收到切换到另一个控制的结合将更新,如果在UI中进行更改。

如果在代码中进行更改,则需要提升NotifyPropertyChanged事件以便绑定系统查看它。

2)这可能不是这种情况,但它给人留下的印象是你试图在你的UserControl属性上设置绑定,这不是数据绑定被设计用于这种特殊用例的方式。你想要的是将non-UI类的数据绑定到UserControl上的依赖项属性。

3)只要你的UI项目有你的类的引用,这永远不会有问题。

4)这是人们在开始使用XAML和WPF时常见的反应。这就好像不是交了一箱乐高玩具,而是交给了一台没有足够指令的注塑机,不是吗?总的来说,这是一种情况,你可能需要检查你的设计; “Model-View-ViewModel”模式的元素将派上用场。如果您对此不熟悉,那么您会在其中引入一个“ViewModel”类的开发模式,也许您可​​以将其称为MasterPartsVM,其中包含INotifyPropertyChanged的实现。

UserControlDataContext将设置为此类MasterPartsVM类。

一个简短的代码示例,使用一些通用名称。给定一个ViewModel类的小支持类,看起来像这样:

class PartViewModel : INotifyPropertyChanged 
{ 

    #region INotifyPropertyChanged Members 

    public event PropertyChangedEventHandler PropertyChanged; 

    #endregion 

    public PartClass Data { get; set; } 

    public String SomeVMProperty 
    { 
     get { return Data.SomeProperty; } 

     set 
     { 
      if (Data.SomeProperty != value) 
       Data.SomeProperty = value; 
      this.PropertyChanged(this, new PropertyChangedEventArgs("SomeVMProperty")); 
     } 
    } 

} 

class PartClass 
{ 
    public string SomeProperty { get; set; } 
} 

一个基本的用户控件的XAML应该是这样的:

<UserControl x:Class="WpfApplication1.PartUserControl" 
      ... > 
    <Grid> 
     <TextBox Text="{Binding SomeVMProperty}" Margin="68,77,104,176" /> 
    </Grid> 
</UserControl> 

要将数据类连接到这个用户控件,设置UserControl的DataContext属性。如果你这样做的代码,它是有你的用户控件的引用和视图模型,然后设置属性的问题:

MyUserControlInstance.DataContext = new PartViewModel(); // or some existing PartViewModel 

的代码组合应努力产生一个文本框,其Text财产变化,每时间SomeVMProperty属性已更改。

+0

非常感谢您提供的信息!我开始看到ModelView在哪里发挥作用。在我的情况下,我有一个包含多个其他类的对象。 ModelView本质上给出了层次结构的'平面'视图,所以XAML只有一个数据上下文来处理。正确? – Falconeer 2010-07-12 16:02:15

+0

或多或少正确,但MVVM模式仍然只是一种模式;在执行该模式的数据绑定合同中没有任何固有的东西。在层次结构中,您可以为用户控件的子元素指定其他数据上下文,这可能会破坏良好的架构理念。对我而言,使ViewModel具有处理数据绑定细节(双向或单向,以及站点转换器的地方)的一点并不需要您修改模型中的代码。 – 2010-07-12 17:36:06

1

在基本约束的情况下,如果你的类看起来像这样

public class MasterPartsData 
{ 
    private string _c0uf; 

    public string C0uf 
    { 
     get { return _c0uf;} 
     set { _c0uf = value;} 
    } 

    public MasterPartsData() 
    { 
     C0uf = "Hello World!"; 
    } 
} 

您的XAML看起来像这样

<Window x:Class="WpfApplication1.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:WpfApplication1" 
    Title="MainWindow" > 
    <Window.DataContext> 
     <local:MasterPartsData /> 
    </Window.DataContext> 

    <Grid> 
     <TextBlock Text="{Binding Path=C0uf}" /> 
    </Grid> 
</Window> 

注意,有很多不同的方法来设置DataContext的,你不并不一定只需要在XAML中执行此外,通常您的MasterDataParts类将实现INotifyPropertyChanged