MVVMを使用していて、1つのウィンドウに2つのリストボックスを表示しています。これらのリストボックスの両方から、AとBと呼ばれる異なるフィールドに同時にバインドしています。AとBは両方ともCを変更しています。これを機能させるには、2つのリストボックスから一度に1つのアイテムのみをIsSelectedにして、A Bが選択されている場合、Cをオーバーライドしません。どうすればこれを制限できますか?
質問する
6065 次
2 に答える
11
これを行うには、いくつかの方法が考えられます。
1つの方法はListBox.SelectedIndex
、2つのリストボックスのをバインドして変更を通知するViewModelプロパティを作成することです。
たとえば、ビューで:
<ListBox SelectedIndex="{Binding SelectedIndexA}">
<ListBoxItem Content="Item 1"/>
<ListBoxItem Content="Item 2"/>
</ListBox>
<ListBox SelectedIndex="{Binding SelectedIndexB}">
<ListBoxItem Content="Item 1"/>
<ListBoxItem Content="Item 2"/>
</ListBox>
そしてあなたのViewModelで:
public int SelectedIndexA
{
get { return _selectedIndexA; }
set
{
_selectedIndexA = value;
_selectedIndexB = -1;
OnPropertyChanged("SelectedIndexB");
}
}
public int SelectedIndexB
{
get { return _selectedIndexB; }
set
{
_selectedIndexB = value;
_selectedIndexA = -1;
OnPropertyChanged("SelectedIndexA");
}
}
もう1つの方法は、「GroupName」のような添付プロパティを使用して、セレクターをグループ化(ListBox
から継承Selector
)して、グループ内の1つだけが一度Selector
に選択されたアイテムを持つようにすることです。
例えば:
public static class SingleSelectionGroup
{
public static readonly DependencyProperty GroupNameProperty =
DependencyProperty.RegisterAttached("GroupName", typeof(string), typeof(SingleSelectionGroup),
new UIPropertyMetadata(OnGroupNameChanged));
public static string GetGroupname(Selector selector)
{
return (string) selector.GetValue(GroupNameProperty);
}
public static void SetGroupName(Selector selector, string value)
{
selector.SetValue(GroupNameProperty, value);
}
private static void OnGroupNameChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
var selector = (Selector) dependencyObject;
if (e.OldValue != null)
selector.SelectionChanged -= SelectorOnSelectionChanged;
if (e.NewValue != null)
selector.SelectionChanged += SelectorOnSelectionChanged;
}
private static void SelectorOnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems.Count == 0)
return;
var selector = (Selector) sender;
var groupName = (string) selector.GetValue(GroupNameProperty);
var groupSelectors = GetGroupSelectors(selector, groupName);
foreach (var groupSelector in groupSelectors.Where(gs => !gs.Equals(sender)))
{
groupSelector.SelectedIndex = -1;
}
}
private static IEnumerable<Selector> GetGroupSelectors(DependencyObject selector, string groupName)
{
var selectors = new Collection<Selector>();
var parent = GetParent(selector);
GetGroupSelectors(parent, selectors, groupName);
return selectors;
}
private static DependencyObject GetParent(DependencyObject depObj)
{
var parent = VisualTreeHelper.GetParent(depObj);
return parent == null ? depObj : GetParent(parent);
}
private static void GetGroupSelectors(DependencyObject parent, Collection<Selector> selectors, string groupName)
{
var childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
var selector = child as Selector;
if (selector != null && (string) selector.GetValue(GroupNameProperty) == groupName)
selectors.Add(selector);
GetGroupSelectors(child, selectors, groupName);
}
}
}
そしてあなたの見解では:
<ListBox my:SingleSelectionGroup.GroupName="Group A">
<ListBoxItem Content="Item 1 (Group A)"/>
<ListBoxItem Content="Item 2 (Group A)"/>
</ListBox>
<ListBox my:SingleSelectionGroup.GroupName="Group A">
<ListBoxItem Content="Item 1 (Group A)"/>
<ListBoxItem Content="Item 2 (Group A)"/>
</ListBox>
<ListBox my:SingleSelectionGroup.GroupName="Group B">
<ListBoxItem Content="Item 1 (Group B)"/>
<ListBoxItem Content="Item 2 (Group B)"/>
</ListBox>
<ListBox my:SingleSelectionGroup.GroupName="Group B">
<ListBoxItem Content="Item 1 (Group B)"/>
<ListBoxItem Content="Item 2 (Group B)"/>
</ListBox>
強調表示される前にアイテムを2回クリックする必要がある場合は、次のような簡単な回避策を使用できます。
<Style TargetType="ListBoxItem">
<Style.Triggers>
<EventTrigger RoutedEvent="GotKeyboardFocus">
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="(ListBoxItem.IsSelected)">
<DiscreteBooleanKeyFrame KeyTime="00:00:00" Value="True" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
于 2012-10-06T16:24:07.753 に答える