使用转换器在列表视图中绑定Silverlight对象

时间:2012-05-23 11:05:07

标签: c# silverlight windows-phone-7 xaml

你好我强制更新列表视图有点问题。 我有ObservableCollection,它包含属性Buffer的TestClass对象。

ObservalbeCollection驻留在ViewModel BaseViewModel

public partial class MainPage : PhoneApplicationPage {
   // Constructor
    public MainPage() {
      InitializeComponent();
      this.DataContext = new BaseViewModel();
    }
  }
}

public class BaseViewModel : INotifyPropertyChanged {
  public ObservableCollection<TestClass> TestList { get; set; }
  public BaseViewModel() {
    TestList = new ObservableCollection<TestClass>();
    TestList.Add(new TestClass() { Buffer = "1", SomeValue = 1 });
    TestList.Add(new TestClass() { Buffer = "2", SomeValue = 2 });
    TestList.Add(new TestClass() { Buffer = "3", SomeValue = 3 });
    TestList.Add(new TestClass() { Buffer = "4", SomeValue = 4 });
  }

  private TestClass selectedItem;
  public TestClass SelectedItem {
    get {
      return selectedItem;
    }
    set {
      if (selectedItem == value) {
        return;
      }

      selectedItem = value;
      selectedItem.Buffer += "a";
      selectedItem.SomeValue += 1;
      selectedItem = null;
      RaisePropertyChanged("SelectedItem");
    }
  }

  #region notifie property changed
  public event PropertyChangedEventHandler PropertyChanged;

  public void RaisePropertyChanged(string propertyName) {
    PropertyChangedEventHandler handler = this.PropertyChanged;
    if (handler != null) {
      handler(this, new PropertyChangedEventArgs(propertyName));
    }
  }
  #endregion
}

public class TestClass : INotifyPropertyChanged  {

  public TestClass() {
  }

  public int SomeValue { get; set; }

  private string buffer;
  public string Buffer {
    get {
      return this.buffer;
    }
    set {
      this.buffer = value;
      RaisePropertyChanged("Buffer");        
    }
  }

  #region notifie property changed
  public event PropertyChangedEventHandler PropertyChanged;

  public void RaisePropertyChanged(string propertyName) {
    PropertyChangedEventHandler handler = this.PropertyChanged;
    if (handler != null) {
      handler(this, new PropertyChangedEventArgs(propertyName));
    }
  }
  #endregion
}

我将视图模型绑定到Page。

Page xaml:

<phone:PhoneApplicationPage 
     xmlns:converters="clr-namespace:PhoneApp2.Test">

<phone:PhoneApplicationPage.Resources>
    <converters:TestClassConverter x:Key="testConverter"/>
</phone:PhoneApplicationPage.Resources>

<ListBox Grid.Row="1" x:Name="tasksListBox" ItemsSource="{Binding TestList}"
                 SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
                 >
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBlock Text="SomeText"/>
                    <TextBlock Text="{Binding Path=Buffer}"/>
                    <TextBlock Text="{Binding Converter={StaticResource testConverter}}"/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

现在第二个文本块在缓冲区更改时正确更新,但第三个文本块仅更新一次(在列表加载时)。转换器只被调用一次。

我想使用第三种选择,因为:

a)我使用TestCalass作为其他子类的基类

b)我想根据TestClass类型格式化输出并使用TestClass中设置的其他参数

c)我想使用Localizable String资源,我不想在TestClass中使用它们而不是POCO对象。

编辑: 我已经更新了源代码。第二个文本框更改而第三个文本框不更改。所有类都期望MainPage驻留:

namespace PhoneApp2.Test

2 个答案:

答案 0 :(得分:0)

如果您更新TestList以在更新时调用RaisePropertyChanged,它是否有效?

(如果你提供了一个完整的复制品,我已经检查了自己。)

答案 1 :(得分:0)

一旦其中一个组件更新,并且如果事件(如PropertyChanged)宣布此更新,则更新绑定。

绑定

<TextBlock Text="{Binding Converter={StaticResource testConverter}}"/>

始终是常量:它始终绑定到相同的列表条目。因此,无论您在此列表条目中更改了什么,都不会通知Binding。

如果引发INotifyCollectionChanged的CollectionChanged事件,将重新评估AFAIK Binding。您可以通过将CollectionChanged事件另外提升到已经引发的PropertyChanged事件来实现此目的 - 但是这会重新评估整个列表并导致性能问题。

编辑:你需要提出TestList的CollectionChanged事件,这可能是不可能的。您可能需要从ObservableCollection中注入BaseViewModel来执行此操作。