ビジネスオブジェクトのデータテンプレートにイベントトリガーを追加するにはどうすればよいですか?
-
07-07-2019 - |
質問
BlinkingLightという名前のカスタムクラスがあります。 また、静的なObservableCollection BlinkingLightCollectionもあります。 UIには、BlinkingLightCollectionにバインドされたListBoxがあります。
ListBoxで、各BlinkingLightオブジェクトを、LEDが1秒だけ点滅してから通常に戻るように見えるアニメーションを持つLEDライトを備えたボックスのように見えるカスタムコントロールとして基本的に表示したい
私のBlinkingLightクラスにはサードパーティの「LED」があります。 「Flash」というイベントを発生させるオブジェクト。
これを機能させるためのアイデアや解決策を探しています!
失敗した試行:
BlinkingLightがカスタムコントロールのDataContextである場合、BlinkingLightクラスのデータにバインドできるカスタムコントロール(BlinkingLightControl)を作成しました。
ListBoxのDataTemplateを作成しました:
<Window.Resources>
<DataTemplate x:Key="blinkingLightItemTemplate" >
<local:BlinkingLightControl />
</DataTemplate>
</Window.Resources>
<ListBox ItemsSource={Binding Source={x:Static local:Data.BlinkingLightCollection}}
ItemTemplate="{StaticResource blinkingLightItemTemplate}" />
注意:カスタムコントロールのxamlをdatatemplateに配置するだけで、物事が簡単になった場合は完全に異なるコントロールを使用できます。
今、私はBlinkingLightControl(またはDataTemplate)にEventTriggerを持ちたいです。RoutedEventはLED.Flashイベントです。残念ながら、この部分を理解することはできません。 BlinkingLightクラスでRoutedEventを作成し、LED.Flashイベントを処理するたびにそれを発生させようとしました。ただし、私のクラスはUIElementまたはContentElementではなく、MSDNごとに: MSNDリンク
&quot;ルーティングイベントの所有者は任意のクラスにすることができますが、ルーティングイベントは有用であるためにUIElementまたはContentElement派生クラスによって発生および処理される必要があります。カスタムイベントの詳細については、「方法:カスタムルーティングイベントを作成する」を参照してください。
ご協力いただければ幸いです!! おかげで、 スコット
解決 2
非常にうまく機能するソリューションを思いつくことができました:
DataTemplateには、カスタムUserControl(DataContextにバインドしてビジネスオブジェクトからデータを取得する)が含まれているだけなので、カスタムRoutedEventをUserControlに配置しました。次に、UserControlのロードされたイベントで、DataContextをビジネスオブジェクトとしてキャストして、イベントを持つビジネスオブジェクトのプロパティにアクセスし、イベントハンドラーに接続します。 (私の例では、DataContextをBlinkingLightオブジェクトとしてキャストすると、そのLedプロパティのFlashイベントにアクセスして、カスタムイベントハンドラーに接続できます)。 注:LEDオブジェクトは、BlinkingLightオブジェクトのフィールドではなく、プロパティである必要があります。
イベントハンドラーは、UserControlのカスタムルーティングイベント(FlashGreenEvent)を発生させることができます。以下は、OP内のコードを補足するバックエンドコードです(他の無関係なコードは削除しました)。
public partial class BlinkingLightControl : UserControl
{
public static readonly RoutedEvent FlashGreenEvent = EventManager.RegisterRoutedEvent("FlashGreen", RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(BlinkingLightControl));
public event RoutedEventHandler FlashGreen
{
add { AddHandler(FlashGreenEvent, value); }
remove { RemoveHandler(FlashGreenEvent, value); }
}
private void BlinkingLightControl_Loaded(object sender, RoutedEventArgs e)
{
BlinkingLight blinkingLight = (BlinkingLight)this.DataContext;
blinkingLight.Led.Flash += LED_Flash;
}
protected delegate void LED_FlashCallback(ThirdParty.LED sender);
public void LED_Flash(ThirdParty.LED sender)
{
if (this.Dispatcher.CheckAccess())
{
// Raise the Flash Green Event;
RaiseEvent(new RoutedEventArgs(BlinkingLightControl.FlashGreenEvent));
}
else
this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new LED_FlashCallback(LED_Flash), sender);
}
}
他のヒント
この場合、WPFコマンドを使用して&quot; BlinkTheLights&quot;を作成するのが最良の方法です。 RoutedCommand-BlinkingLightControlはBlinkTheLightsコマンドを処理し、ライトが点滅するStoryBoardを開始して応答します。
カスタムコントロールを作成している場合は、コントロールテンプレートの外部で常にトリガーを設定できます。
次のようなもの:
<Style TargetType="{x:Type local:MyControl}">
<!-- fade in the control with an animation -->
<Style.Triggers>
<EventTrigger RoutedEvent="Control.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation To="1" Duration="0:0:1" Storyboard.TargetProperty="Opacity"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
<!-- Make sure the opacity starts at 0 -->
<Setter Property="Opacity" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MyControl}">
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>