我正在嘗試RountedEvent從 a 的多個實體中捕獲 a UserControl。Window通過在級別(本地:MyControl.MyEvent =“Window_CodeBehindHandler”)捕獲路由事件,這很容易在非 MVVM 世界中作業。但是我需要將該事件轉發到視圖模型,并且我正在努力獲得一個Interaction.Triggers行為相同的設定。EventTrigger如果我傳入特定的SourceName或將 UserControlSourceObject的內部放在 XAML 中,則其行為與預期Interaction.Triggers相同,但這并不相同。
我嘗試了各種版本的設定SourceName或SourceObject控制元件型別或名稱,但沒有運氣。
我在這里整理了一個 MRE:WpfInteractionEventTriggerMRE。“真正的”實作ItemsView系結到在運行時創建的這些控制元件物件的集合,比單個“選擇”事件發生的更多,因此“只需使用已實作 Click 的 {x} 控制元件并重新設定它的樣式”建議沒有幫助。
<Window x:Class="WpfApp5.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp5"
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800"
local:ElipseControl.Select="Window_Select"> <!-- This works as expected -->
<b:Interaction.Triggers> <!-- This does not -->
<b:EventTrigger EventName="Select">
<b:InvokeCommandAction Command="{Binding ElipseSelectedCommand}" />
</b:EventTrigger>
</b:Interaction.Triggers>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<local:ElipseControl Grid.Row="0" ElipseName="One" />
<local:ElipseControl Grid.Row="1" ElipseName="Two" />
</Grid>
</Window>
我希望有一些我只是在這里俯瞰的東西。
uj5u.com熱心網友回復:
您正在使用的EventTrigger不支持附加事件。您要么必須實作自己的自定義事件觸發器,要么只需從Window_Select視窗中的事件處理程式呼叫命令:
var viewModel = DataContext as YourViewModel;
if (viewModel != null)
viewModel.ElipseSelectedCommand.Execute(null);
這不會以任何方式破壞 MVVM 模式,因為與使用互動觸發器相比,您從相同的視圖呼叫相同的命令。MVVM 并不是要從視圖中消除代碼 - 它是關于關注點分離。
uj5u.com熱心網友回復:
自定義事件觸發器有效。原始問題中的 MRE 已更新。這是相關的更新代碼。
<Window x:Class="WpfApp5.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp5"
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<b:Interaction.Triggers>
<local:RoutedEventTrigger RoutedEvent="local:ElipseControl.Select" >
<b:InvokeCommandAction Command="{Binding ElipseSelectedCommand}" PassEventArgsToCommand="True" />
</local:RoutedEventTrigger>
</b:Interaction.Triggers>
<Grid>
<ItemsControl ItemsSource="{Binding Elipses}" />
</Grid>
</Window>
根據自定義事件觸發器,稍微更新的版本:
public class RoutedEventTrigger : EventTriggerBase<DependencyObject>
{
private RoutedEventHandler _eventHandler;
public RoutedEvent RoutedEvent { get; set; }
public RoutedEventTrigger()
{
}
protected override void OnAttached()
{
var associatedElement = GetAssociatedElement();
if (associatedElement != null && RoutedEvent != null)
{
_eventHandler = new RoutedEventHandler(OnRoutedEvent);
associatedElement.AddHandler(RoutedEvent, _eventHandler);
}
}
protected override void OnDetaching()
{
var associatedElement = GetAssociatedElement();
if (associatedElement != null && RoutedEvent != null && _eventHandler != null)
{
associatedElement.RemoveHandler(RoutedEvent, _eventHandler);
}
base.OnDetaching();
}
private FrameworkElement GetAssociatedElement()
{
FrameworkElement associatedElement = null;
if (AssociatedObject is Behavior behavior)
{
associatedElement = ((IAttachedObject)behavior).AssociatedObject as FrameworkElement;
}
else if (AssociatedObject is FrameworkElement frameworkElement)
{
associatedElement = frameworkElement;
}
if (associatedElement == null)
{
throw new ArgumentException("Routed Event Trigger can only be associated to framework elements");
}
return associatedElement;
}
private void OnRoutedEvent(object sender, RoutedEventArgs e) => base.OnEvent(e);
protected override string GetEventName() => RoutedEvent?.Name ?? string.Empty;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/527032.html
標籤:C#wpf
