2013-04-07 146 views

回答

0

您可以在视图中添加您的视图模型单独的属性和独立的组合框,然后操纵时的值值改变视图模型,但是这很麻烦,而且涉及大量的工作,当你添加一个新的组合框(值)。

更好的方法是创建一个自定义集合处理的变化:

public class ValueHolder<T> : INotifyPropertyChanged 
{ 
    private T _value; 
    public T Value 
    { 
     get { return _value; } 
     set 
     { 
      if (!EqualityComparer<T>.Default.Equals(value, _value)) 
      { 
       T old = _value; 
       _value = value; 
       OnPropertyChanged("Value"); 
       OnValueChanged(old, value); 
      } 
     } 
    } 

    public ValueHolder() 
    { 
    } 

    public ValueHolder(T value) 
    { 
     this._value = value; 
    } 

    public event EventHandler<ValueChangedEventArgs<T>> ValueChanged; 
    public event PropertyChangedEventHandler PropertyChanged; 

    protected void OnValueChanged(T oldValue, T newValue) 
    { 
     var h = ValueChanged; 
     if (h != null) 
      h(this, new ValueChangedEventArgs<T>(oldValue, newValue)); 
    } 

    protected virtual void OnPropertyChanged(string propName) 
    { 
     var h = PropertyChanged; 
     if (h != null) 
      h(this, new PropertyChangedEventArgs(propName)); 
    } 
} 

public class ValueChangedEventArgs<T> : EventArgs 
{ 
    public T OldValue { get; set; } 
    public T NewValue { get; set; } 

    public ValueChangedEventArgs(T oldValue, T newValue) 
    { 
     this.OldValue = oldValue; 
     this.NewValue = newValue; 
    } 
} 

public class MyCollection<T> : Collection<ValueHolder<T>> 
{ 
    public void Add(T i) 
    { 
     this.Add(new ValueHolder<T>(i)); 
    } 

    private void AddChangeHandler(ValueHolder<T> item) 
    { 
     item.ValueChanged += item_ValueChanged; 
    } 

    private void RemoveChangeHandler(ValueHolder<T> item) 
    { 
     item.ValueChanged -= item_ValueChanged; 
    } 

    protected override void InsertItem(int index, ValueHolder<T> item) 
    { 
     AddChangeHandler(item); 
     base.InsertItem(index, item); 
    } 

    protected override void RemoveItem(int index) 
    { 
     RemoveChangeHandler(this[index]); 
     base.RemoveItem(index); 
    } 

    protected override void ClearItems() 
    { 
     foreach (var item in this) 
     { 
      RemoveChangeHandler(item); 
     } 
     base.ClearItems(); 
    } 

    protected override void SetItem(int index, ValueHolder<T> item) 
    { 
     RemoveChangeHandler(this[index]); 
     AddChangeHandler(item); 
     base.SetItem(index, item); 
    } 

    private void item_ValueChanged(object sender, ValueChangedEventArgs<T> e) 
    { 
     ValueHolder<T> v = (ValueHolder<T>)sender; 
     for (int i = 0; i < this.Count; i++) 
     { 
      if (this[i] == v) 
       continue; 
      if (EqualityComparer<T>.Default.Equals(this[i].Value, e.NewValue)) 
      { 
       this[i].Value = e.OldValue; 
       break; 
      } 
     } 
    } 
} 

然后定义您的视图模型是这样的:

public class MyViewModel 
{ 
    private MyCollection<int> _values; 

    public MyViewModel() 
    { 
     _values = new MyCollection<int>() { 1, 2, 3, 4, 5 }; 
    } 

    public MyCollection<int> Values 
    { 
     get { return _values; } 
    } 
} 

,并在您的XAML:

<ItemsControl ItemsSource="{Binding Path=Values}" Margin="10"> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
      <StackPanel Orientation="Horizontal"/> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
      <ComboBox SelectedValue="{Binding Path=Value}" Margin="5"> 
       <ComboBox.ItemsSource> 
        <Int32Collection >1,2,3,4,5</Int32Collection> 
       </ComboBox.ItemsSource> 
      </ComboBox> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 

这是很多代码!但是,这个任务很好,而且是非常可维护的。

+0

不错!但在xaml中的多个或分隔的组合框中呢? – Jesson 2013-04-07 13:08:47

+0

此代码的伟大工程..但不是它不适合我的XAML我有5个分开的组合框怎么我想每个值,并将其保存在我的数据库..是有分离组合框任何其他的方法呢? – Jesson 2013-04-07 13:26:32

0

在你的数据模型只需切换值。因此,当数据模型的属性发生更改时,wpf控件将会更新。

XAML:

<Window x:Class="WpfApplication2.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:model="clr-namespace:WpfApplication2" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.Resources> 
     <model:DataModel x:Key="MyModel" /> 
    </Window.Resources> 
    <Grid> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="Auto" /> 
     </Grid.ColumnDefinitions> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="Auto" /> 
     </Grid.RowDefinitions> 

     <ItemsControl Grid.Column="0" Grid.Row="0" DataContext="{StaticResource MyModel}" 
         ItemsSource="{Binding Items}"> 
      <ItemsControl.ItemsPanel> 
       <ItemsPanelTemplate> 
        <StackPanel Orientation="Horizontal" /> 
       </ItemsPanelTemplate> 
      </ItemsControl.ItemsPanel> 
      <ItemsControl.ItemTemplate> 
       <DataTemplate> 
        <ComboBox SelectedItem="{Binding SelectedItem}" ItemsSource="{Binding Items}"> 
        </ComboBox> 
       </DataTemplate> 
      </ItemsControl.ItemTemplate> 
     </ItemsControl> 
    </Grid> 
</Window> 

代码:

using System.Collections.Generic; 
using System.ComponentModel; 
using System.Diagnostics; 

namespace WpfApplication2 
{ 
    public class DataModel 
    { 
     #region Construction and Initialization 

     public DataModel() 
     { 
      var elements = new[] {1, 2, 3, 4, 5}; 
      Items = new List<ItemsModel> 
       { 
        new ItemsModel(elements, 1), 
        new ItemsModel(elements, 2), 
        new ItemsModel(elements, 3), 
        new ItemsModel(elements, 4), 
        new ItemsModel(elements, 5) 
       }; 

      foreach (var itemsModel in Items) 
      { 
       itemsModel.PropertyChanged += SelectedItemChanged; 
      } 
     } 

     #endregion 

     public List<ItemsModel> Items { get; private set; } 

     private void SelectedItemChanged(object sender, PropertyChangedEventArgs e) 
     { 
      if (e.PropertyName == "SelectedItem") 
      { 
       var model = sender as ItemsModel; 
       Debug.Assert(model != null, "model != null"); 
       int pos = Items.IndexOf(model) + 1; 
       Items[model.SelectedItem - 1].SelectedItem = pos; 
      } 
     } 
    } 

    public class ItemsModel: INotifyPropertyChanged 
    { 
     #region Construction and Initialization 

     public ItemsModel(IEnumerable<int> items, int selectedItem) 
     { 
      Items = items; 
      _selectedItem = selectedItem; 
     } 

     #endregion 

     public int SelectedItem 
     { 
      get { return _selectedItem; } 
      set 
      { 
       if (_selectedItem != value) 
       { 
        _selectedItem = value; 
        RaisePropertyChanged("SelectedItem"); 
       } 
      } 
     } 

     private int _selectedItem; 

     public IEnumerable<int> Items { get; private set; } 

     public event PropertyChangedEventHandler PropertyChanged; 

     private void RaisePropertyChanged(string propertyName) 
     { 
      PropertyChangedEventHandler handler = PropertyChanged; 
      if (handler != null) 
      { 
       handler(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 
    } 
} 
+0

可以显示一些示例代码? – Jesson 2013-04-07 07:13:50

+0

添加的代码示例。 – Alexey 2013-04-07 17:37:12

1

这样,你就应该这样做。你应该提出哪些用户可以拖放,为了改变用鼠标用户拔插用户控件。

您的解决方案是不是很好,但如果你仍然想这样做,然后在组合框中选择信息的事件看,通过与其它有价值的组合框并将其更改为上一个。