3

XamlReader.Parse(string) を使用してデータ テンプレートを動的に構築しています。私が抱えている問題は、XamlReader を使用して作成したコントロールにイベントを配置できないことです。オンラインで調査を行った結果、これが XamlReader の既知の制限であることがわかりました。

WPF のコマンドについてはよくわかりませんが、どうにかしてそれらを使用して同じ結果を得ることができますか? もしそうなら、どのように?そうでない場合、Xaml Reader を使用して作成されたコントロールからコード ビハインドでイベントを処理する方法はありますか?

以下は、私が作成するデータテンプレートの例です。このデータ テンプレートをホストする Window のコード ビハインドで、MenuItem_Click イベント ハンドラを定義しています。

実行しようとすると、次のエラーが表示されます: System.Windows.Markup.XamlParseException was unhandled: Failed to create a 'Click' from the text 'MenuItem_Click'.

DataTemplate result = null;
        StringBuilder sb = new StringBuilder();

        sb.Append(@"<DataTemplate 
                        xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
                        xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
                            <Grid Width=""Auto"" Height=""Auto"">

                            <TextBlock Text=""Hello"">
                                <TextBlock.ContextMenu>
                                    <ContextMenu>
                                         <MenuItem 
                                          Header=""World""
                                          Click=""MenuItem_Click""></MenuItem>
                                    </ContextMenu>
                                </TextBlock.ContextMenu>
                            </TextBlock>

                            </Grid>
                      </DataTemplate>");

        result = XamlReader.Parse(sb.ToString()) as DataTemplate;
4

2 に答える 2

5

遅い答えが他の人を助けるかもしれないことを願っています:

解析後にイベントをバインドする必要があり、Xaml 文字列からクリック イベントを削除する必要があることがわかりました。

私のシナリオでは、結果の DataTemplate を ItemTemplate に適用し、ItemSource を接続してから、ハンドラーを追加しました。これは、クリックイベントがすべてのアイテムで同じであることを意味しますが、私の場合、ヘッダーは必要な情報であり、メソッドは同じでした.

//Set the datatemplate to the result of the xaml parsing.
myListView.ItemTemplate = (DataTemplate)result;

//Add the itemtemplate first, otherwise there will be a visual child error
myListView.ItemsSource = this.ItemsSource; 

//Attach click event.
myListView.AddHandler(MenuItem.ClickEvent, new RoutedEventHandler(MenuItem_Click));

そして、クリック イベントは元のソースに戻る必要があります。送信者は、DataTemplate を使用していた私の場合は ListView になります。

internal void MenuItem_Click(object sender, RoutedEventArgs e){
    MenuItem mi = e.OriginalSource as MenuItem;
    //At this point you can access the menuitem's header or other information as needed.
}
于 2012-02-09T19:11:49.147 に答える
0

このリンクを見てください。そこにあるソリューションのほとんどは、同様に適用さParseれます。私は実際には C# 開発者ではないので、本当に説明できるのは最後のものだけです。これは、if-all-else-fails オプションのようなものです。

最初に、クリックなどの属性の代わりに ID を XAML に追加します。次に、FindLogicalNodeを使用してノードを取得し、自分でイベントを結び付けることができます。

たとえば、 MenuItem を指定するとしますID="WorldMenuItem"。次に、parse を呼び出した後のコードで、これを行うことができます。

MenuItem worldMenuItem = (MenuItem)LogicalTreeHelper.FindLogicalNode(result, "WorldMenuItem");
worldMenuItem.Click += MenuItem_Click; // whatever your handler is
于 2010-08-20T16:01:19.600 に答える