如何以简单的方式管理 ComboBox 中的自动切换号码?
问问题
454 次
3 回答
1
你不应该那样做。您应该向用户展示可交换的用户控件,哪些用户可以拖放,用鼠标更改顺序。
您的解决方案不是很好,但如果您仍然想这样做,那么在组合框 selectitem 事件中查看具有该值的其他组合框并将其更改为前一个。
于 2013-04-07T09:10:43.327 回答
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));
}
}
}
}
于 2013-04-07T06:40:13.023 回答
0
您可以在 ViewModel 中添加单独的属性,在视图中添加单独的 ComboBox,然后在 ViewModel 中更改值时操作值,但这很麻烦,并且在添加新的 ComboBox(值)时涉及大量工作。
更好的方法是创建一个处理更改的自定义集合:
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;
}
}
}
}
然后像这样定义您的 ViewModel:
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>
这是很多代码!但是很好地完成了任务,并且非常易于维护。
于 2013-04-07T10:25:35.550 回答