【问题标题】:WPF XAML Button Click handler in InlineUIContainer problemInlineUIContainer 问题中的 WPF XAML 按钮单击处理程序
【发布时间】:2011-06-15 11:51:41
【问题描述】:

我有一个 FlowDocument,其中包含如下元素:

<InlineUIContainer>
   <Button Click="Button_Click" Tag="123456789890">
      <Image Source="Images\Image1.png" />
   </Button>
</InlineUIContainer>

这存储在一个 .xaml 文件中,并在某个时候通过执行以下操作来加载:

flowDocument = XamlReader.Load(xamlFile, parserContext) as FlowDocument;
flowDocumentReader.Document = flowDocument;

加载失败并出现以下错误:

XamlParseException - 无法从文本“Button_Click”创建“Click”

Button_Click 方法是存在于 FlowDocumentReader 所在的 MainWindow 中的方法,其想法是按钮的 Tag 具有一些标识符(库存 ID),并且单击处理程序将使用该库存 ID 执行某些操作。

如果 FlowDocument 在 MainWindow.xaml 中,则此 Button_Click 事件处理程序一切正常,但我怀疑当它从磁盘加载文件时,它对处理程序一无所知。

我该如何解决这个问题?想法?


更新

虽然我认为 Pavlo 的解决方案可行,但我最终执行了以下操作,并且似乎效果很好。在我的 FlowDocumentReader Xaml 中,我添加了以下内容:

<FlowDocumentReader ButtonBase.Click="Button_Click">

并从按钮的 xaml 中删除了单击事件。我仍在努力处理 WPF 和 XAML,但我相信这个常见的单击处理程序可以工作,因为路由事件。当我加载的 FlowDocument 中的任何按钮发生 Click 时,它会冒泡,直到找到一个处理程序,在我的例子中是 FlowDocumentReader 元素中指定的处理程序。

尽管我因不理解而感到沮丧,但它以这种方式工作真是太好了。


更新 2:

依赖路由事件来处理我的 FlowDocument 按钮的 Click 事件的副作用是,属于 FlowDocumentReader 本身的按钮最终会将其 Click 事件冒泡到我创建的这个包罗万象的处理程序中,即绝对不是我想要发生的。

为了解决这个问题,我目前依赖于处理程序中的事实,它看起来像这样:

private void Button_Click(object sender, RoutedEventArgs e)
{
   if (e.Source is Button)
   {
      MessageBox.Show("Button in doc clicked");
   }
}

RoutedEventArgs 中的“Source”成员对于 FlowDocument 中的按钮是“Button”,对于属于 FlowDocumentReader 的按钮是“FlowDocumentReader”。虽然我很想听听其他想法,但似乎可行。

【问题讨论】:

    标签: wpf xaml event-handling flowdocument


    【解决方案1】:

    您可以尝试以下方法。为您的按钮命名,并在加载FlowDocument 后使用FindName 检索按钮并连接Click 处理程序。

    <InlineUIContainer>
       <Button x:Name="MyButton" Tag="123456789890">
          <Image Source="Images\Image1.png" />
       </Button>
    </InlineUIContainer>
    

    -

    flowDocument = XamlReader.Load(xamlFile, parserContext) as FlowDocument;
    flowDocumentReader.Document = flowDocument;
    
    Button myButton = (Button)flowDocument.FindName("MyButton");
    myButton.Click = Button_Click;
    

    如果您的按钮不是唯一的并且您无法为其命名,请考虑在文档中查找所有类型为 Button 且将 Tag 属性设置为 ID 的对象。

    【讨论】:

    • 我认为您的解决方案会奏效。请参阅我为解决此问题所做的问题的更新。
    【解决方案2】:

    如果您创建自定义按钮类(从按钮派生)并添加您自己的自定义点击事件定义。然后,您可以添加一个特定于您的自定义事件的处理程序。无需担心从其他按钮拾取意外事件。

    在你的按钮类中声明新事件

     Public Shared ReadOnly ButtonClickEvent As RoutedEvent = _
                   EventManager.RegisterRoutedEvent("ButtonClick", RoutingStrategy.Bubble, _
                   GetType(RoutedEventHandler), GetType(MyButton))
    
    ' Provide CLR accessors for the event
    Public Custom Event ButtonClick As RoutedEventHandler
        AddHandler(ByVal value As RoutedEventHandler)
            Me.AddHandler(ButtonClickEvent, value)
        End AddHandler
    
        RemoveHandler(ByVal value As RoutedEventHandler)
            Me.RemoveHandler(ButtonClickEvent, value)
        End RemoveHandler
    
        RaiseEvent(ByVal sender As Object, ByVal e As RoutedEventArgs)
            Me.RaiseEvent(e)
        End RaiseEvent
    End Event
    

    在自定义按钮类的点击处理程序中引发新的 RoutedEvent

        Private Sub MyButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            RaiseEvent ButtonClick(Me, New RoutedEventArgs(MyButton.ButtonClickEvent))
        End Sub
    

    在 FlowDocumentReader 或其他顶级元素上使用事件处理程序来侦听。 (我的流文档查看器周围有一个 GroupBox,并在该级别添加了处理程序)

     <GroupBox Header="Document editor" local:MyButton.ButtonClick="OnButtonClick" >
    

    【讨论】:

      猜你喜欢
      • 2012-04-12
      • 1970-01-01
      • 1970-01-01
      • 2016-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-11
      • 2012-05-23
      相关资源
      最近更新 更多