我有一个AutoSuggestBox。当我输入内容时,它会给我一个"建议"的列表。该列表是Popup中的ListView。无论哪种方式,我都希望禁用列表中的某些项目,因此用户无法选择它们。
我做得很好,我的实现如下:
<AutoSuggestBox x:Name="AutoSuggest" ...
ItemContainerStyle="{StaticResource
MyPopUpListViewItemStyle}"
/>
<Style x:Key="MyPopUpListViewItemStyle" TargetType="ListViewItem">
...
<Setter Property="helpers:SetterValueBindingHelper.PropertyBinding">
<Setter.Value>
<helpers:SetterValueBindingHelper
Property="IsEnabled"
Binding="{Binding Path=Content.IsItemEnabled, RelativeSource={RelativeSource Self}}" />
</Setter.Value>
</Setter>
...
</Style>
我在样式中绑定属性时遇到了一些问题。但是现在一切正常,ListViewItems&#39; &#34;的IsEnabled&#34;属性绑定到其内容中的属性。所以现在,用户无法用鼠标选择特定项目。
我的问题是!虽然用户不能用鼠标选择项目,但他仍然可以使用向上↑和向下↓箭头选择它(并且不仅仅选择它们,而实际上选择回车)。我希望用户跳过禁用的项目(仍然可以使用箭头选择常规项目。)
我搜索了很长一段时间,我确实找到了一个很好看的解决方案,可以绑定&#34; Focusable&#34;从ListViewItem属性到我自己的属性,但它只是WPF,因为那里没有&#34;可聚焦&#34;我的ListViewItem的属性。
所有可能的ListViewItem属性,包括:&#34; AllowFocusOnInteraction&#34;,&#34; IsTabStop&#34;,&#34; AllowFocusWhenDisabled&#34;,&#34; IsHitTestVisible&#34;和其他逻辑相关的东西都没有用。
答案 0 :(得分:0)
经过几个小时的挣扎后,我找到了解决问题的方法。该解决方案与我在问题中发布的方式有所不同。它不会跳过禁用的项目(当遇到带箭头键的禁用项目时跳过第一个启用的项目)。相反,它允许用户像其他任何人一样突出显示禁用的项目,但它不允许他用&#34; Enter&#34;键。无论哪种方式,用户都可以理解该项目已被禁用,首先是因为它是灰色的(因为它的&#34; IsEnabled&#34;设置为false),其次,我将文本的前景设置为内部禁用的ItemListView为红色。
不允许用户选择&#34;输入&#34;只需捕捉&#34;输入&#34;在KeyDown方法中返回&#34;没有做任何事情&#34;。问题是在哪里获得所需的KeyDown方法。
我有自己的AutoSuggestBox样式(主要是原来的Windows&#39; AutoSuggestBox,我不记得有人改变任何事情),如下所示:
<Style TargetType="AutoSuggestBox">
...
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="AutoSuggestBox">
<Grid>
...
<TextBox x:Name="TextBox"
...
/>
<Popup x:Name="SuggestionsPopup">
<Border x:Name="SuggestionsContainer">
<Border.RenderTransform>
<TranslateTransform x:Name="UpwardTransform" />
</Border.RenderTransform>
<ListView
x:Name="SuggestionsList"
...
>
<ListView.ItemContainerTransitions>
<TransitionCollection />
</ListView.ItemContainerTransitions>
</ListView>
</Border>
</Popup>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
可以看出,AutoSuggestBox的想法是带有搜索的TextBox,以及与它相同级别的Popup。 Popup包含一个ListView of&#34; advice&#34;根据TextBox上面的文字吧。他们按名字&#34; TextBox&#34; &安培; &#34; SuggestionsList&#34;
TextBox(原始名称&#34; TextBox&#34;)是您想要捕获&#34; KeyDown&#34;的主要元凶。活动到。我们的想法是,当您使用上下箭头键查看建议列表时,您的焦点始终保留在同一文本框中,而不是列表视图或其他任何内容。
所以我所做的就是向TextBox(上面那个样式中的那个)添加一个Behavior,如下所示:
<TextBox x:Name="TextBox"
... >
<interactivity:Interaction.Behaviors>
<TheNamespaceContainingClass:BehaviorClassName />
</interactivity:Interaction.Behaviors>
</TextBox>
行为类代码: 我添加了几条评论来进一步解释重要部分
public class BehaviorClassName: DependencyObject, IBehavior
{
private TextBox _associatedObject;
private ListView _listView;
public DependencyObject AssociatedObject
{
get
{
return _associatedObject;
}
}
public void Attach(DependencyObject associatedObject)
{
_associatedObject = associatedObject as TextBox;
if (_associatedObject != null)
{
_associatedObject.KeyDown -= TextBox_OnKeyDown;
_associatedObject.KeyDown += TextBox_OnKeyDown;
}
}
private void TextBox_OnKeyDown(object sender, KeyRoutedEventArgs e)
{
if (_associatedObject != null)
{
if (_listView == null)
{
// Gets ListView through visual tree. That's a hack of course. Had to put it here since the list initializes only after the textbox itself
_listView = (ListView)((Border)((Popup)((Grid)_associatedObject.Parent).Children[1]).Child).Child;
}
if (e.Key == VirtualKey.Enter && _listView.SelectedItem != null)
{
// Here I had to make sure the Enter key doesn't work only on specific (disabled) items, and still works on all the others
// Reflection I had to insert to overcome the missing reference to the needed ViewModel
if (!((bool)_listView.SelectedItem.GetType().GetProperty("PropertyByWhichIDisableSpecificItems").GetValue(_listView.SelectedItem, null)))
e.Handled = true;
}
}
}
public void Detach()
{
_associatedObject.KeyDown -= TextBox_OnKeyDown;
}
}
这可能不是最简单的解释和解决方案,但问题也不是很简单。如果遇到这个具体问题,希望你能想出整个想法。如果你不遵循MVVM和/或不关心质量,整个问题可以通过更简单的方式解决,但主要思想保持不变。
此外,我在问题中发布的SetterValueBindingHelper来自this博客。非常感谢其作者SuperJMN。