私はウィンドウの左側にWPF TreeViewを持つMVVMアプリケーションを持っています。 右側の詳細パネルは、選択したツリーノードに応じて内容を変更します。マウスかキーで選択されているか調べるには?
ユーザーがノードを選択すると、詳細内容パネルがすぐに変更されます。 ユーザーがノードをクリックした場合は望ましいですが、ユーザーがキーの下/上を使用してツリーをナビゲートすると、コンテンツの変更が遅れることがあります。 (少なくともWindows XPではWindows XPと同じ動作) マウスまたはキーボードでノードが選択されている場合は、ViewModelで知っている必要があります。
どうすればこの問題を解決できますか?
更新:
これは、したがって、これは適切な場所であれば、私はわからないんだけど、私はコミュニティが、私はその間に何をしたか知らせてほしい私の最初の投稿です。ここに私自身の解決策があります。私は専門家ではないので、良い解決策であるかどうかはわかりません。しかし、それは私のために働く、それが他人を助けるなら私は幸せになるだろう。バグ修正、改善、またはより良い解決策が高く評価されています。
私はHasMouseFocus ...
は(最初に私がMouseEnterEventを使用しますが、ユーザーがキーアップ/ダウンでツリーをナビゲートし、マウスポインタが任意のナビゲート木の上にランダムであれば、これはうまく動作しない添付プロパティの下に作成項目、その場合には、詳細はすぐに更新されるため。)
public static bool GetHasMouseFocus(TreeViewItem treeViewItem)
{
return (bool)treeViewItem.GetValue(HasMouseFocusProperty);
}
public static void SetHasMouseFocus(TreeViewItem treeViewItem, bool value)
{
treeViewItem.SetValue(HasMouseFocusProperty, value);
}
public static readonly DependencyProperty HasMouseFocusProperty =
DependencyProperty.RegisterAttached(
"HasMouseFocus",
typeof(bool),
typeof(TreeViewItemProperties),
new UIPropertyMetadata(false, OnHasMouseFocusChanged)
);
static void OnHasMouseFocusChanged(
DependencyObject depObj, DependencyPropertyChangedEventArgs e)
{
TreeViewItem item = depObj as TreeViewItem;
if (item == null)
return;
if (e.NewValue is bool == false)
return;
if ((bool)e.NewValue)
{
item.MouseDown += OnMouseDown;
item.MouseLeave += OnMouseLeave;
}
else
{
item.MouseDown -= OnMouseDown;
item.MouseLeave -= OnMouseLeave;
}
}
/// <summary>
/// Set HasMouseFocusProperty on model of associated element.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
static void OnMouseDown(object sender, MouseEventArgs e)
{
if (sender != e.OriginalSource)
return;
TreeViewItem item = sender as TreeViewItem;
if ((item != null) & (item.HasHeader))
{
// get the underlying model of current tree item
TreeItemViewModel header = item.Header as TreeItemViewModel;
if (header != null)
{
header.HasMouseFocus = true;
}
}
}
/// <summary>
/// Clear HasMouseFocusProperty on model of associated element.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
static void OnMouseLeave(object sender, MouseEventArgs e)
{
if (sender != e.OriginalSource)
return;
TreeViewItem item = sender as TreeViewItem;
if ((item != null) & (item.HasHeader))
{
// get the underlying model of current tree item
TreeItemViewModel header = item.Header as TreeItemViewModel;
if (header != null)
{
header.HasMouseFocus = false;
}
}
}
...とTreeView.ItemContainerStyle
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}" >
<!-- These Setters binds some properties of a TreeViewItem to the TreeViewItemViewModel. -->
<Setter Property="IsExpanded" Value="{Binding Path=IsExpanded, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<Setter Property="ToolTip" Value="{Binding Path=CognosBaseClass.ToolTip}"/>
<!-- These Setters applies attached behaviors to all TreeViewItems. -->
<Setter Property="properties:TreeViewItemProperties.PreviewMouseRightButtonDown" Value="True" />
<Setter Property="properties:TreeViewItemProperties.BringIntoViewWhenSelected" Value="True" />
<Setter Property="properties:TreeViewItemProperties.HasMouseFocus" Value="True" />
</Style>
</TreeView.ItemContainerStyle>
に適用し プロパティは、添付プロパティのパスです。 HasMousefocusPropertyがtrueの場合
xmlns:properties="clr-namespace:WPF.MVVM.AttachedProperties;assembly=WPF.MVVM"
はその後、私のViewModelに、私はすぐに詳細パネル(GridViewコントロール)を更新。 falseの場合は、単にDispatcherTimerを起動し、現在選択されている項目をTagとして適用します。間隔が500msになると、Tick-Eventは詳細を適用しますが、選択した項目がTagと同じである場合に限ります。
/// <summary>
/// This property is beeing set when the selected item of the tree has changed.
/// </summary>
public TreeItemViewModel SelectedTreeItem
{
get { return Property(() => SelectedTreeItem); }
set
{
Property(() => SelectedTreeItem, value);
if (this.SelectedTreeItem.HasMouseFocus)
{
// show details for selected node immediately
ShowGridItems(value);
}
else
{
// delay showing details
this._selctedNodeChangedTimer.Stop();
this._selctedNodeChangedTimer.Tag = value;
this._selctedNodeChangedTimer.Start();
}
}
}
次のようにSOの質問では、キーバインディングの問題を扱います。http://stackoverflow.com/a/7086853/1416258およびhttp://stackoverflow.com/a/918062/1416258個人的な状況は、周りを遊んで、または誰かがあなたに魚を与えるのを待つ。 –
多くの感謝@Geoist。 Cammandバインディングを使用すると、ユーザーが指定したキーを押すとすぐにViewModelにフラグを設定できます。しかし、ユーザーが別のツリーノードを選択したとき(またはその前に)、このフラグをクリアする必要があります。何か案は? – AelanY
@AelanYはい、あなたはこのフラグをリセットする必要があります。あなたの詳細パネルのリフレッシュを開始しているロジックに最適な場所が必要です。 – akjoshi