【问题标题】:Using Events/Commands with XamlReader将事件/命令与 XamlReader 一起使用
【发布时间】:2010-08-20 15:18:48
【问题描述】:

我正在使用 XamlReader.Parse(string) 动态构建我的数据模板。我遇到的问题是我无法在使用 XamlReader 创建的任何控件上放置任何事件。在网上做了一些研究后,我了解到这是 XamlReader 的一个已知限制。

我对 WPF 中的命令了解不多,但我能以某种方式使用它们来获得相同的结果吗?如果有怎么办?如果没有,有什么方法可以处理我的代码中的事件,该事件来自使用 Xaml Reader 创建的控件?

以下是我创建的数据模板的示例。我在将托管此数据模板的窗口的代码隐藏中定义了 MenuItem_Click 事件处理程序。

尝试运行时出现以下错误:System.Windows.Markup.XamlParseException 未处理:无法从文本“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;

【问题讨论】:

    标签: c# .net wpf xaml xamlreader


    【解决方案1】:

    希望迟到的答案可能对其他人有所帮助:

    我发现我需要解析后绑定事件,不得不从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.
    }
    

    【讨论】:

      【解决方案2】:

      看看this link。那里的大多数解决方案也适用于Parse。我不是真正的 C# 开发人员,所以我唯一能真正解释的是最后一个,这是一个 if-all-else-fails 选项:

      首先,将 ID 添加到 XAML 而不是 Click 等属性。然后您可以使用FindLogicalNode 获取节点,然后自己连接事件。

      例如,假设您给 MenuItem ID="WorldMenuItem"。然后在你的代码中调用 parse 后,你可以这样做:

      MenuItem worldMenuItem = (MenuItem)LogicalTreeHelper.FindLogicalNode(result, "WorldMenuItem");
      worldMenuItem.Click += MenuItem_Click; // whatever your handler is
      

      【讨论】:

      • 我似乎无法编译该 sn-p。 FindLogicalNode 将 DependencyObject 作为第一个参数,我不知道如何将 DataTemplate 转换为 DependencyObject。有什么想法吗?
      • 我想我知道如何从 DataTemplate 中获取 DependencyObject ...我使用 DataTemplate.LoadContent()。现在的问题是,无论 MenuItem 是什么,都永远找不到。我知道上下文菜单不包含在与其他控件相同的 VisualTree 中,LogicalTree 也是如此吗?
      猜你喜欢
      • 1970-01-01
      • 2020-10-03
      • 1970-01-01
      • 2012-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-10
      • 1970-01-01
      相关资源
      最近更新 更多