mau*_*kye 6 silverlight binding command listbox mvvm
我一直在阅读很多关于MVVM(特别是使用Laurent Bugnion的库)的文章,而且我一直在努力确定如何在MVVM中做一些事情,而这些事情在代码背后很容易实现.
这里只是一个例子,我怀疑自己正在以艰难的方式做事.如果有人有时间阅读这些内容,也许他们可以评论我的方法的合理性.:)
我有一个绑定到ViewModel的列表框,如下所示:
<ListBox x:Name="lstFruitBasketLeft" ItemsSource="{Binding FruitBasket}" 
     SelectedItem="{Binding SelectedFruit, Mode=TwoWay}"  Width="150">
<ListBox.ItemTemplate>
    <DataTemplate>
        <StackPanel Orientation="Horizontal" VerticalAlignment="Center" 
                    HorizontalAlignment="Left" Margin="2">
            <TextBlock Text="{Binding Name}" />
            <TextBlock Text=":" />
            <TextBlock Text="{Binding Quantity}" />
        </StackPanel>
    </DataTemplate>
</ListBox.ItemTemplate>
ItemSource是Fruit对象的ObservableCollection:
public class Fruit
{
    public string Name { get; set; }
    public int Quantity { get; set; }
    public Fruit() { }
    public Fruit(string name, int quantity) 
    {
      this.Name = name;
      this.Quantity = quantity;
    }
  }
它在ViewModel中定义为:
// Property FruitBasket
public const string FruitBasketPropertyName = "FruitBasket";
private ObservableCollection<Fruit> _fruitBasket = null;
public ObservableCollection<Fruit> FruitBasket
{
  get { return _fruitBasket; }
  set
  {
    if (_fruitBasket == value)
      return;
    _fruitBasket = value;
    // Update bindings, no broadcast
    RaisePropertyChanged(FruitBasketPropertyName);
  }
}
绑定的SelectedItem属性如下:
//Property SelectedFruit
public const string SelectedFruitPropertyName = "SelectedFruit";
private Fruit _selectedFruit = null;
public Fruit SelectedFruit
{
  get { return _selectedFruit; }
  set
  {
    if (_selectedFruit == value)
      return;
    var oldValue = _selectedFruit;
    _selectedFruit = value;
    // Update bindings, no broadcast
    RaisePropertyChanged(SelectedFruitPropertyName);
  }
}
然后,列表将填充ViewModel的构造.
现在,我将一个RelayCommand添加到演示文稿页面上的一个按钮,该按钮执行一个增加所选项目数量的方法.请注意,我还没有使用该参数,但"Bob"是一个占位符,可以在以后进行某些更改.
<Button x:Name="butMore" Content="More!" HorizontalAlignment="Right" Height="25" Width="75" Margin="4">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Click">
            <cmd:EventToCommand
                Command="{Binding addMoreCommand}"
                CommandParameter="Bob" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Button>
这是命令的代码:
// Property addMoreCommand
public RelayCommand addMoreCommand
{
  get;
  private set;
}
...
  //Init relays (this is in the constructor)
  addMoreCommand = new RelayCommand(AddFruit, CanExecute);
...
public void AddFruit()
{
  //Increment the fruit
  SelectedFruit.Quantity++;
  //Save the previous selected item
  Fruit oldSelectedItem = SelectedFruit;
  //We have to have a new list in order to get the list box to refresh
  FruitBasket = new ObservableCollection<Fruit>(FruitBasket);
  //Reselect
  SelectedFruit = oldSelectedItem;
}
public bool CanExecute()
{
  return true; //for now
}
现在这确实有效,但我遇到了一些问题:
首先,我觉得有很多条件必须聚集在一起才能工作,我想知道我是否会如此幸运地试图将一些Telerik拖放代码移动到MVVM中.
其次,重新创建这样的列表似乎是一种非常糟糕的性能方法.
最后,似乎这在后面的代码中会更容易(虽然我不是100%肯定我仍然不必重建该列表).
有没有人对我的方法有任何想法,或者甚至是......让事情变得简单的建议?我只是错过了一些明显的东西吗?
谢谢
-Dodiodilate:]
莫尔基,
如果您必须刷新ObservableCollection. 通常,您不需要它,因为它将ObservableCollection通知项目更改。
切勿这样做:
FruitBasket = new ObservableCollection<Fruit>(FruitBasket);
您public ObservableCollection<Fruit> FruitBasket应该没有公共设置器,它应该是只读的。只是Add或Remove来自列表的项目。
如果您想处理多个选择,您可能需要一个CollectionView可以处理此问题的扩展,请在此处获取更多提示。
我希望这能有所帮助,即使我可能没有回答所有问题:)
编辑: 好的,我想我做错了一些事情。现在我想我完全理解你想要实现的目标。当您的财产发生变化时,您不会收到通知,对吧?出于这个原因,我们在我们的一个项目中采用了“ BindableLinq ”,您可以在 Silverlight 中毫无问题地进行编译。(有类似的解决方案可用,称为Continuous Linq或Obtics,您可以选择)。
使用BindableLinq,您可以将您的方法转换ObservableCollection为BindableCollection使用单一扩展方法。然后,遗嘱BindableCollection将正确反映所有更改。试一试。
EDIT2: 要实现正确的ViewModel,请考虑以下更改。
1)Fruit是你的Model。由于它没有实现INotifyPropertyChanged,因此不会传播任何更改。创建一个FruitViewModel,嵌入您的Fruit模型并RaisePropertyChanged为每个属性设置器调用。
2) 将您的更改FruitBasket为ObservableCollectionof FruitViewModel。慢慢地它开始有意义:)
3)也SelectedFruit必须是a 。FruitViewModel现在它更有意义了。
4)现在它已经对我有用了,即使没有BindableLinq. 你有成功吗?
华泰
最好的问候,
托马斯
| 归档时间: | 
 | 
| 查看次数: | 3960 次 | 
| 最近记录: |