【发布时间】:2017-02-20 08:27:18
【问题描述】:
情况:在 MVVM 模式中,我在列表视图上有一些输入绑定,它们仅在列表视图获得焦点时才起作用。但是,每当用户单击时,列表视图就会失去焦点,并且用户无法执行输入绑定。
问题:我想以输入绑定工作的方式将焦点放在列表视图上(在按钮单击时)。
我尝试了什么: 我尝试使用附加属性 IsFocused(我使用 UIElement.Focus() 和/或 Keyboard.Focus() 聚焦)并将其绑定到 ViewModel 中的 bool 变量,我将使用 ICommand 设置该变量。
我还尝试了一个单独的示例,我可以在后面的代码中使用 System.Windows.Input.Keyboard.Focus(item) 方法(我的意思是同名的 .xaml.cs 文件)来聚焦列表视图和有用!但是,我不知道如何在使用 d:DesignInstance 属性连接的 ViewModel 中实现类似的东西。
我相信 mouseclick 事件会冒泡并在其他地方处理,这会导致列表在我单击它时立即失焦。就像,如果我找到一种方法将事件设置为已处理,这将有所帮助,但我不知道如何在视图模型中做到这一点。这是我的附加财产:
FocusExtension.cs
public static class FocusExtension {
public static bool GetIsFocused(DependencyObject obj) {
return (bool)obj.GetValue(IsFocusedProperty);
}
public static void SetIsFocused(DependencyObject obj, bool value) {
obj.SetValue(IsFocusedProperty, value);
}
public static readonly DependencyProperty IsFocusedProperty =
DependencyProperty.RegisterAttached(
"IsFocused", typeof(bool), typeof(FocusExtension),
new UIPropertyMetadata(false, OnIsFocusedPropertyChanged));
private static void OnIsFocusedPropertyChanged(
DependencyObject d,
DependencyPropertyChangedEventArgs e) {
var uie = (UIElement)d;
if ((bool)e.NewValue) {
uie.Focus();
}
}
}
XAML 文件:
<ListView
x:Name="lv"
Grid.Column="2" Margin="2" MinWidth="250" Height="400" ToolTip="the List"
HorizontalContentAlignment="Stretch"
ItemsSource="{Binding ListBindingInVM}"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.CanContentScroll="False"
dd:DragDrop.IsDragSource="True"
dd:DragDrop.IsDropTarget="True"
dd:DragDrop.DropHandler="{Binding }"
behaviour:ListViewAutoScroll.AutoScrollToEnd="True"
ScrollViewer.VerticalScrollBarVisibility="Visible"
>
<ListView.Style>
<Style TargetType="ListView" >
<Setter Property="ViewModels:FocusExtension.IsFocused" Value="{Binding ListFocused, Mode=TwoWay}"></Setter>
<!--The one below is not clean, but worked. However, list goes out of focus on click. -->
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="ViewModels:FocusExtension.IsFocused" Value="True"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</ListView.Style>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDown">
<!--This command sets the ListFocused to true-->
<i:InvokeCommandAction Command="{Binding BringListToFocus }"></i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
<ListView.InputBindings>
<!-- Bindings that don't work when list is not focused-->
<KeyBinding Modifiers="Control" Key="C" Command="{Binding CopyCommand}"/>
<KeyBinding Modifiers="Control" Key="V" Command="{Binding PasteCommand}"/>
</ListView.InputBindings>
<ListView.ContextMenu>
<ContextMenu>
<MenuItem Header="Copy" Command= "{Binding CopyCommand}"></MenuItem>
<MenuItem Header="Paste" Command= "{Binding PasteCommand}"></MenuItem>
</ContextMenu>
</ListView.ContextMenu>
【问题讨论】:
-
MVVM != 没有代码隐藏。这确实意味着您的视图模型中没有特定于 UI 的代码。正如您所发现的,尝试将焦点集中在您的虚拟机中并不是最好的主意。旁注,如果您遇到事件问题,请抓住 Snoop。它会跟踪事件并告诉您阻止冒泡的元素。
-
感谢您的评论 :) 我知道,但是我正在研究的“指南”希望我在代码隐藏中放置任何代码。使用 snoop 将是一个漫长的过程,与团队成员交谈之类的。是否有可能对 xaml 和/或 viewmodel 的任何更改有一些解决方法?
-
推回准则。而且 Snoop 不是一个“冗长的过程”,它是一个应用程序,可以向您展示 WPF UI 中正在发生的事情,包括绑定错误、事件传播和其他好处。这是一个很棒的工具,而且是免费的。
-
为什么 listview / listviewitem 会失焦?当您单击它时,listview / listviewitem 不应失去焦点。我会解决这个问题,而不是尝试在错误之上进行创可贴?
-
谢谢,但没有。您应该添加一个答案,详细说明问题所在以及您为解决问题所做的工作。然后你可以接受它是正确的并关闭这个问题。
标签: c# wpf xaml windows-phone-7 mvvm