C#Wpf绑定到Userdefined类的集合不能按预期工作

时间:2017-04-22 07:49:30

标签: c# wpf mvvm binding

目前我的Viewmodel中有一个MyClass的ObservableCollection。我使用此Collection的getter从其他Datasource填充它。我现在可以在窗口(网格)中显示此数据并显示正确的数据,但是当我更改数据时,不会触发该集合(我认为这是因为集合没有被更改,只有集合中的元素)。我应该为MyClass的每个属性创建一个属性,所以我可以对单个值的更改做出反应,我问自己的问题是:

  • 我如何知道目前选择的元素
  • 如果我对每件商品都有约束力,如何正确填写收藏品

当我的Collection更改时,我也想到了一个事件,但我不确定如何正确实现它。

public ObservableCollection<MyClass<string>> SelectedParams
{
  get
  {
    //Fill the Collection
  }
  set
  {
    //I think here i want to react to changed Textboxvalues in my View
  }
}
 public class MyClass<T> : INotifyPropertyChanged
 {
   public event PropertyChangedEventHandler PropertyChanged;
   private T _curValue;
   private string _value1;
   private string _value2;

   public string Value1
   {
     get
     {
       return _value1;
     }
     set
     {
       if (_value1 != value)
       {
         _value1 = value;
         PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Value1)));
       }
     }
   }
   public string Value2
   {
     get
     {
       return _value2;
     }
     set
     {
       if (_value2 != value)
       {
         _value2 = value;
         PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Value2)));
       }
     }
   }
   public T curValue
   {
     get
     {
       return _curValue;
     }
     set
     {
       _curValue = value;
       PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(curValue)));
     }
   }

   public MyClass()
   {
   }
   public MyClass(string val1, string val2, T curVal)
   {
     Value1 = val1;
     Value2 = val2;
     curValue = curVal;
   }
 }

xaml代码看起来像这样

<ItemsControl ItemsSource="{Binding SelectedParams}">
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <Grid HorizontalAlignment="Stretch">
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="*"/>
          <ColumnDefinition Width="*"/>
          <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Label Grid.Column="0"  Content="{Binding Value1}"/>
        <Label Grid.Column="1"  Content="{Binding Value2}"/>
        <TextBox Grid.Column="2" Text="{Binding curValue, Mode=TwoWay}"/>
      </Grid>
    </DataTemplate>
  </ItemsControl.ItemTemplate>
</ItemsControl>

Edit1:将MyClass更改为INotifyPropertyChanged现在Collection更改了内部值但是在更改值时仍未调用Setter

2 个答案:

答案 0 :(得分:0)

您需要为MyClass实现INotifyPropertChanged接口,并在setter中引发PropertyChanged以通知UI属性值已更改。

答案 1 :(得分:0)

  

我如何知道目前选择的元素

如果您想要支持项目选择,则必须使用其他控件。 ItemsControl不支持选择。

以ListView为例。将ItemsSource和SelectedItem绑定到您的类。现在,每次单击某个项目时,SelectedValue都会更新。如果从代码更改SelectedValue,UI将更新列表中的选定项。您也可以将其他控件绑定到SelectedValue,就像我使用ListView外部的TextBlock一样。

查看

<StackPanel>
    <ListView ItemsSource="{Binding Values}" SelectedItem="{Binding SelectedValue}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding Path=Item1}" />
                    <TextBlock Text="=" />
                    <TextBlock Text="{Binding Path=Item2}" />
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    <StackPanel Orientation="Horizontal">
        <TextBox Text="Selected:" Background="DarkGray" />
        <TextBox Text="{Binding SelectedValue.Item1, Mode=OneWay}" Background="DarkGray" />
    </StackPanel>
</StackPanel>

数据

public class ListViewBindingViewModel : INotifyPropertyChanged
{
    private Tuple<string,int> _selectedValue;

    public ObservableCollection<Tuple<string,int>> Values { get; }

    public Tuple<string, int> SelectedValue
    {
        get { return _selectedValue; }
        set
        {
            _selectedValue = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedValue)));
        }
    }

    public ListViewBindingViewModel()
    {
        Values = new ObservableCollection<Tuple<string, int>> {Tuple.Create("Dog", 3), Tuple.Create("Cat", 5), Tuple.Create("Rat",1)};
    }

}