-4

如何以简单的方式管理 ComboBox 中的自动切换号码?

问题示例

4

3 回答 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 回答