我正在使用MVVM并在一个窗口中显示两个列表框。我将这两个列表框同时绑定到不同的字段上,称为A和B.然后A和B都修改C.为了实现这个功能,我只想从两个列表框中选择一个IsSelected,这样A当B IsSelected时不覆盖C.我怎样才能限制呢?一次只选择一个项目的多个WPF列表框
谢谢!
我正在使用MVVM并在一个窗口中显示两个列表框。我将这两个列表框同时绑定到不同的字段上,称为A和B.然后A和B都修改C.为了实现这个功能,我只想从两个列表框中选择一个IsSelected,这样A当B IsSelected时不覆盖C.我怎样才能限制呢?一次只选择一个项目的多个WPF列表框
谢谢!
我可以想到几种方法来做到这一点。
一种方法是您可以绑定您的2个ListBoxes的ListBox.SelectedIndex
来更改 - 通知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");
}
}
另一种方法是用像“组名”附加属性其中您可以选择器(ListBox
从继承Selector
)以确保组中只有一个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>
如果你必须点击一个项目之前两次将突出显示,你可以使用一个快速的解决方法是这样的:
<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>
很好的答案!我已经对下面的答案进行了一些修正。我仍然有一个小问题。如果你可以尝试解决这个问题,那么它会对你很好。如果你变得免费,那么请看看我的问题在这里:http://stackoverflow.com/questions/22209877/movefocus-from-one-listbox-to-another – Vishal
如果有人在ItemsControl中使用了ListBox/ListView,并且存在以下问题使用上述答案后:
以下XAML只需添加到您的ListBoxItem的风格:
<Style TargetType="ListBoxItem">
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="IsSelected" Value="True"></Setter>
</Trigger>
</Style.Triggers>
</Style>
而且,如果有人在上面的回答使用代码后发现了以下错误:
GroupName is already registered by Selector
请将依赖项属性声明中的third parameter typeof(......)
更改为您的类名称。
当在另一个ListBox中进行选择时,您想要在一个ListBox中清除选择?我发现你的问题很难理解。 – Simon
我基本上想知道如何将我的视图模型中的东西像IsFocused/IsSelected Listbox属性绑定到布尔。 – user1722960
您可以将ListBox的SelectedIndex绑定到视图模型中的属性。因此,例如,当设置ListBoxA的SelectedIndexA时,可以将ListBoxB的SelectedIndexB设置为-1以清除ListBoxB的选择,反之亦然。这是你的意图吗? – Simon