绑定到集合中的各个元素

时间:2011-12-08 22:06:44

标签: wpf xaml binding mvvm collections

我对MVVM很新,所以请耐心等待。我有一个视图模型类,其公共属性实现如下:

public List<float> Length
{
  get;
  set;
}

在我的视图的XAML中,我有几个文本框,每个文本框都绑定到此长度列表中的特定元素:

  <TextBox Text="{Binding Length[0], Converter=DimensionConverter}" />
  <TextBox Text="{Binding Length[2], Converter=DimensionConverter}" />
  <TextBox Text="{Binding Length[4], Converter=DimensionConverter}" />

DimensionConverter是一个IValueConverter派生类,它将值格式化为维度(即屏幕上的文本框中480.0英寸变为40'0“),然后再返回(即字符串需要35'0”,产生420.0)英寸为源)

我的问题:我需要能够验证List中的每个值,因为它在关联的TextBox中已更改。对于某些人,我可能需要根据输入的值修改List中的其他值(即更改Length [0]处的float将更改Length [4]处的值并更新屏幕)。

有没有办法重新处理属性以允许索引器?或者,我是否需要为列表中的每个项目创建单独的属性(这真的使List不必要)?基本上,因为我已经拥有了float的集合,所以我希望能够编写MVVM代码来验证每个项目的修改。

思考? (并且,提前感谢)

4 个答案:

答案 0 :(得分:1)

您可以使用ObservableCollection<float>代替List<float>,并处理CollectionChanged事件以检测用户何时更改值。

答案 1 :(得分:1)

不会是这样的:

    <ItemsControl ItemsSource="{Binding Length}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <TextBox Text="{Binding Mode=TwoWay, Converter=DimensionConverter}" />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

接近你想要的东西?
它将显示整个列表,并允许用户修改值,只要您的IValueConverter实现ConvertBack,它们将直接返回到列表。

然后像Thomas所说的那样验证或实施ObservableLinkedList

你现在所做的事情看起来很脏,而且只有几行代码......

答案 2 :(得分:1)

如果你有一个实现INotifyPropertyChanged的类来提供列表长度不变的属性,那就太好了。

答案 3 :(得分:1)

如果要使用mvvm验证文本输入,请创建一个可以在viewmodel中使用的模型

public class FloatClass : INotifyPropertyChanged
{
  private ICollection parentList;

  public FloatClass(float initValue, ICollection pList) {
    parentList = pList;
    this.Value = initValue;
  }

  private float value;

  public float Value {
    get { return this.value; }
    set {
      if (!Equals(value, this.Value)) {
        this.value = value;
        this.RaiseOnPropertyChanged("Value");
      }
    }
  }

  private void RaiseOnPropertyChanged(string propName) {
    var eh = this.PropertyChanged;
    if (eh != null) {
      eh(this, new PropertyChangedEventArgs(propName));
    }
  }

  public event PropertyChangedEventHandler PropertyChanged;
}

在您的viewmodel中,您可以使用此类型号

public class FloatClassViewmModel : INotifyPropertyChanged
{
  public FloatClassViewmModel() {
    this.FloatClassCollection = new ObservableCollection<FloatClass>();
    foreach (var floatValue in new[]{0f,1f,2f,3f}) {
      this.FloatClassCollection.Add(new FloatClass(floatValue, this.FloatClassCollection));
    }
  }

  private ObservableCollection<FloatClass> floatClassCollection;

  public ObservableCollection<FloatClass> FloatClassCollection {
    get { return this.floatClassCollection; }
    set {
      if (!Equals(value, this.FloatClassCollection)) {
        this.floatClassCollection = value;
        this.RaiseOnPropertyChanged("FloatClassCollection");
      }
    }
  }

  private void RaiseOnPropertyChanged(string propName) {
    var eh = this.PropertyChanged;
    if (eh != null) {
      eh(this, new PropertyChangedEventArgs(propName));
    }
  }

  public event PropertyChangedEventHandler PropertyChanged;
}

这是xaml示例

<ItemsControl ItemsSource="{Binding Path=FloatClassViewmModel.FloatClassCollection}">
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <TextBox Text="{Binding Value, Mode=TwoWay, Converter=DimensionConverter}" />
    </DataTemplate>
  </ItemsControl.ItemTemplate>
</ItemsControl>

希望这会有所帮助