gpt4 book ai didi

c# - 为什么使用 Caliburn Micro Conductor.OneActive 时,Blend Interaction 事件触发器会多次触发?

转载 作者:行者123 更新时间:2023-12-03 10:36:11 25 4
gpt4 key购买 nike

[请注意,我在第一次尝试诊断时问了错误的问题 - 现在已更正。]

我有一个 WPF 应用程序,其中一个主窗口继承自 Conductor.Collection.OneActive。它处理导航请求并保留 View 模型的缓存,以便维护状态。此私有(private)集合几乎与 base.Items 集合相同,但并非所有 View 模型都是 IScreen。

当我们从一个事件项目移动到另一个事件项目时,一切正常并且状态保持不变。但是,交互触发器存在错误。当事件项目是一个 IScreen 时,触发器每次导航都会触发一次额外的时间,就好像它们每次都重新连接一样;普通触发器不这样做,只有来自交互库的触发器。如果事件项不是 IScreen - 只是从 PropertyChangedBase 继承 - 我们看不到这个问题,而且我们在导航期间丢失了 View 的状态。

如果您四次导航到一个 View ,事件将触发四次、五次、五次等等。

这似乎是一样的as this question但我不能使用他的解决方案,因为我不知 Prop 体的 View 模型是什么,也不能为它们创建公共(public)属性。

我的主窗口类如下所示:

public sealed class MainWindowViewModel : Conductor<object>.Collection.OneActive, IHandle<NavigateToUriMessage>
{
public void Handle(NavigateToUriMessage message)
{
var ignoredUris = RibbonUri.GetItems().Where(t => t.SubTabs.Count > 0).Select(t => t.Uri);

Func<string, bool> isMatch = uri => uri == message.Uri;

if (isMatch(RibbonUri.BookkeepingBatchView.Uri))
GetAndActivateViewModel<BatchPanelViewModel>(message);
...
}

private T GetAndActivateViewModel<T>(NavigateToUriMessage message) where T : class
{
var vm = GetViewModel<T>(message.Uri);
ActivateItem(vm);
return (T) vm;
}

private object GetViewModel<T>(string uri) where T : class
{
if (viewModelCache.ContainsKey(uri))
return viewModelCache[uri];
var vm = viewModelFactory.Create<T>();
viewModelCache.Add(uri, vm);
return vm;
}
}

我的 MainWindow XAML 如下所示:
<Window x:Class="Ui.Views.MainWindowView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
d:DataContext="{d:DesignInstance Type=viewModels:MainWindowViewModel, IsDesignTimeCreatable=False}"
mc:Ignorable="d"
WindowState="Maximized" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="1"/>
<RowDefinition/>
<RowDefinition Height="1"/>
<RowDefinition Height="25"/>
</Grid.RowDefinitions>
<ContentControl x:Name="MainRibbon" Grid.Row="0" Margin="0" />
<Grid Background="#FFBBBBBB" Grid.Row="1" />
<ContentControl Grid.Row="2" x:Name="ActiveItem" Background="White" />
<Grid Grid.Row="3" Background="#FFBBBBBB"/>
<ContentControl x:Name="BottomStatusBar" Grid.Row="4"/>
</Grid>
</Window>

事件项 View 中的 XAML 如下所示:
<DataGrid Focusable="True" FocusVisualStyle="{x:Null}" SelectionMode="Single" HeadersVisibility="None" IsReadOnly="True" GridLinesVisibility="None" AutoGenerateColumns="False" Background="Transparent" BorderThickness="0"  Grid.Row="3" Grid.RowSpan="2">
<i:Interaction.Triggers>
<ei:KeyTrigger Key="Left" FiredOn="KeyUp" ActiveOnFocus="True" >
<cal:ActionMessage MethodName="TryCollapseSelectedItem"/>
</ei:KeyTrigger>
<ei:KeyTrigger Key="Right" FiredOn="KeyUp" ActiveOnFocus="True" >
<cal:ActionMessage MethodName="TryExpandSelectedItem"/>
</ei:KeyTrigger>
</i:Interaction.Triggers>
....

最佳答案

好像this question here has a better answer ,尽管隐藏在已接受答案的评论中。 KeyTrigger 类是有问题的,并且每次将子控件重新加载到 ContentControl 时都会附加事件。 @gunter 说,“真正的问题似乎是 OnLoaded 上的钩子(Hook),并且选项卡控件上的元素会获得多个 OnLoaded 事件。”然后@dain 说:“好的,我明白了。好吧,KeyTrigger 是一个公共(public)类,所以你可以扩展它并覆盖 OnEvent 以防止多个事件处理程序附加?”

所以我实现了@dain 的建议,覆盖了 KeyTrigger 类并停止了多次连接事件:

public class MyKeyTrigger : KeyTrigger
{
private bool eventAttached;

protected override void OnEvent(EventArgs eventArgs)
{
if (eventAttached) return;
base.OnEvent(eventArgs);
eventAttached = true;
}

protected override void OnDetaching()
{
eventAttached = false;
base.OnDetaching();
}

关于c# - 为什么使用 Caliburn Micro Conductor.OneActive 时,Blend Interaction 事件触发器会多次触发?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27568159/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com