2017-10-04 10 views
0

私はWPFのRoutedCommandsを頭に入れようとしています。私は彼らが異なるUI要素とモデル間の結合を減らすのが好きですが、ウィンドウの子であるカスタムコントロールのバインディングを動作させるように見えません。私はこれがあなたのWPFウィザードのいずれかのためのいくつかの簡単な信用になると思う!サブ要素でバインドされたRoutedCommandsは決して実行されません。

ルーティングされたコマンド:

using System.Windows.Input; 

namespace Wpf.RoutedCommands 
{ 
    public static class Commands 
    { 
     public static readonly RoutedCommand SayHi = new RoutedCommand(); 
    } 
} 

メインウィンドウのXAML:

<Window x:Class="Wpf.RoutedCommands.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:Wpf.RoutedCommands" 
    mc:Ignorable="d" 
    Title="MainWindow" Height="350" Width="525"> 
<!-- uncommenting the below makes it work but introduces coupling --> 
<!--<Window.CommandBindings> 
    <CommandBinding Command="{x:Static local:Commands.SayHi}" Executed="cmdSayHi" CanExecute="cmdCanSayHi"></CommandBinding> 
</Window.CommandBindings>--> 
<DockPanel LastChildFill="True"> 
    <Button DockPanel.Dock="Bottom" Content="Say Hi!" Command="{x:Static local:Commands.SayHi}" /> 
    <local:Greeter x:Name="Greeter" /> 
</DockPanel>  

メインウィンドウのコード:-)

はここで試してみたことができるいくつかのサンプルコードです:

using System.Windows.Input; 

namespace Wpf.RoutedCommands 
{ 
    public partial class MainWindow 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
     } 

     // these two will be used if you uncomment the command bindings in XAML 
     private void cmdCanSayHi(object sender, CanExecuteRoutedEventArgs e) => e.CanExecute = true; 

     private void cmdSayHi(object sender, ExecutedRoutedEventArgs e) => Greeter.SayHi(); 
    } 
} 

カスタムコントロール( "グリーター")XAML:

<UserControl x:Class="Wpf.RoutedCommands.Greeter" 
     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" 
     xmlns:local="clr-namespace:Wpf.RoutedCommands" 
     mc:Ignorable="d" 
     d:DesignHeight="300" d:DesignWidth="300"> 
<UserControl.CommandBindings> 
    <CommandBinding Command="{x:Static local:Commands.SayHi}" Executed="cmdSayHi" CanExecute="cmdCanSayHi"/> 
</UserControl.CommandBindings> 
<Grid> 
    <Label x:Name="Label" /> 
</Grid> 

グリーターコード:あなたはWPFプロジェクトを作成し、使用している場合

using System.Windows.Input; 

namespace Wpf.RoutedCommands 
{ 
    public partial class Greeter 
    { 
     public Greeter() 
     { 
      InitializeComponent(); 
     } 

     private void cmdSayHi(object sender, ExecutedRoutedEventArgs e) => SayHi(); 

     private void cmdCanSayHi(object sender, CanExecuteRoutedEventArgs e) => e.CanExecute = true; 

     public void SayHi() => Label.Content = "Hi!"; 
    } 
} 

あなたの上のボタンがわかりますメインウィンドウでは無効になります。デバッグすると、Greeter.cmdCanSayHiメソッドが呼び出されないことがわかります。

メインウィンドウで休止状態のXAMLのコメントを外すと、すべて機能します。だから、なぜ私はウィンドウからのコマンドにバインドできますが、その子コントロールからはバインドできません。レンダリングのタイミングなどと関係がありますか?

答えて

1

RoutedCommandは一致CommandBindingを有しており、この特定のCommandBindingためExecuteデリゲートを実行する要素の集束素子とアップからビジュアルツリーを検索します。

UserControlは、以下、Buttonの要素ツリーにあります。

+0

これは確かに説明しています。ルーティングされたコマンドがそのように設計された理由も知っていますか? –