Comment puis-je gérer le numéro de commutateur automatique dans ComboBox de manière simple et rapide?C# WPF ComboBox Numéro de commutateur automatique
Répondre
Vous pouvez ajouter des propriétés séparées dans votre ViewModel et séparer les zones de liste déroulantes dans la vue, puis manipuler les valeurs lorsqu'une valeur change dans ViewModel, mais cela est fastidieux et implique beaucoup de travail lorsque vous ajoutez une nouvelle zone de liste.).
Une meilleure approche est de créer une collection personnalisée qui gère les changements:
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;
}
}
}
}
Réglez ensuite votre ViewModel comme ceci:
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; }
}
}
et dans votre 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>
Ceci est beaucoup de code! Mais fait la tâche bien, et est également très maintenable.
zappent valeurs dans votre modèle de données. Par conséquent, les contrôles wpf seront mis à jour lorsque les propriétés du modèle de données seront modifiées.
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>
code:
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));
}
}
}
}
Vous ne devriez pas le faire de cette façon. Vous devez présenter les commandes utilisateur permutables que l'utilisateur peut faire glisser et déposer, en changeant l'ordre avec la souris.
Votre solution n'est pas très bonne, mais si vous voulez toujours faire cela, dans l'événement selectitem de la liste déroulante, regardez les autres combobox avec cette valeur et remplacez-la par la précédente.
- 1. Commutateur de liste déroulante automatique dans WPF
- 2. C# WPF - ComboBox
- 3. Commutateur de tabulation automatique
- 4. valeur dans combobox C# wpf
- 5. C# Strange WPF Combobox Comportement
- 6. Combobox Élément sélectionné WPF C#
- 7. Sauvegarde automatique - WPF C#
- 8. Propriété IsEditable de WPF combobox
- 9. C# Databound ComboBox Mise à jour automatique
- 10. WPF autocomplete Combobox
- 11. WPF Autocomplete utilisant Combobox
- 12. C# WPF Redimensionner le numéro
- 13. WPF ComboBox Sélection automatique Si 1 seul article
- 14. Liaison Combobox WPF Question
- 15. Hériter ComboBox dans WPF en utilisant C#
- 16. ComboBox SelectedValue ou SelectedItem Binding WPF C#
- 17. wpf dataagrid colonne combobox
- 18. C#, WPF ComboBox avec deux éléments à l'intérieur
- 19. ComboBox IsEditable Behaviour question WPF
- 20. Styling WPF ComboBox éléments
- 21. WPF DataTemplate ComboBox de liant
- 22. WPF zone de recherche combobox
- 23. WPF - Problème de liaison ComboBox
- 24. Définir SelectedItem de WPF ComboBox
- 25. WPF ComboBox ajouter l'article
- 26. wpf dataagrid textbox + combobox
- 27. Combobox multiligne dans WPF
- 28. WPF ComboBox DropDown Placement
- 29. WPF: Combobox dans TreeviewItem
- 30. SelectionChanged Combobox WPF
bien! mais qu'en est-il dans un ComboBox multiple ou séparé dans xaml? – Jesson
ce code fonctionne super .. mais pas son pas sur mon xaml j'ai 5 combobox séparé je veux obtenir chaque valeur et l'enregistrer sur ma base de données .. y at-il une autre approche pour ComboBox séparé? – Jesson