WPF NotifyIcon 中 ItemsControl 中按钮的命令绑定

Posted

技术标签:

【中文标题】WPF NotifyIcon 中 ItemsControl 中按钮的命令绑定【英文标题】:Command binding for button in ItemsControl in WPF NotifyIcon 【发布时间】:2017-01-31 18:25:50 【问题描述】:

我在我的应用程序中使用 hardcodet 的 WPF NotifyIcon,它是使用 MVVM Light 实现的。我正在尝试为图标创建自定义 TrayPopup。在这个弹出窗口中,我有一个 ItemsControl,它的 ItemsSource 是我的 ViewModel 中的对象“NumberList”列表。对于我的 DataTemplate,我使用了一个网格,它显示了我的源对象的一个​​名为“Id”的属性和一个按钮。我试图在我的 ViewModel 中绑定到 RelayCommand 的按钮。过去,我通过使用 RelativeSource 绑定来获取 Window Ancestor 的 DataContext,对 ItemsControls 做过类似的事情。这次我尝试了类似的方法,但是当我运行应用程序时,打开 TrayPopup,然后单击按钮没有任何反应。我的命令没有在我的 ViewModel 中触发。

作为一项测试,我尝试将另一个按钮添加到我的 TrayPopup 并将其命令绑定到我的 ViewModel 中的同一个按钮。该绑定工作正常,所以据我所知,这不是命令。

就像我说的,我在过去几乎完全使用过这种技术,只是以前从未在 NotifyIcon 中使用过。我尝试在按钮绑定到我的窗口名称中指定 ElementName,但没有成功。我也尝试将 RelativeSource 更改为父 TaskbarIcon,但也没有成功。

这里是 NotifyIcon 有同样问题的示例实现:

<tb:TaskbarIcon PopupActivation="LeftOrRightClick">
        <tb:TaskbarIcon.TrayPopup>
            <Grid Background="White">
                <Grid.RowDefinitions>
                    <RowDefinition Height="200"/>
                    <RowDefinition Height="30"/>
                </Grid.RowDefinitions>
                <ScrollViewer Grid.Row="0">
                    <ItemsControl ItemsSource="Binding NumberList, Mode=OneWay, UpdateSourceTrigger=PropertyChanged">
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="200"/>
                                        <ColumnDefinition/>
                                    </Grid.ColumnDefinitions>

                                    <Label Grid.Column="0" Content="Binding Id, Mode=OneWay, UpdateSourceTrigger=PropertyChanged"/>
                                    <Button Grid.Column="1" Content="Test" Command="Binding RelativeSource=RelativeSource FindAncestor, AncestorType=x:Type Window, Path=DataContext.TestCommand"/> <!--This binding doesn't work!-->
                                </Grid>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate>
                                <StackPanel/>
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>
                    </ItemsControl>
                </ScrollViewer>

                <Button Grid.Row="1" Content="Test2" Command="Binding TestCommand"/> <!--This works-->
            </Grid>
        </tb:TaskbarIcon.TrayPopup>
    </tb:TaskbarIcon>

我相当有信心 ViewModel 中的所有内容都是正确的,因为我一直在使用我不久前编写的这个应用程序的早期版本。到目前为止,除了这个 NotifyIcon 之外,我还没有遇到任何问题。有什么想法吗?

【问题讨论】:

【参考方案1】:

在尝试了一段时间后,我找到了问题的答案。我的 ItemsPanelTemplate 中的 StackPanel 具有 DataContext,其中包含我想将按钮绑定到的命令,即我的主 ViewModel。通过为 StackPanel 指定名称,我可以将按钮的 ElementName 设置为其名称,然后绑定就起作用了。不知道为什么这个方法适用于 StackPanel 而不是主窗口。

无论如何,如果有人遇到同样的问题,这里是更新的代码:

<tb:TaskbarIcon PopupActivation="LeftOrRightClick">
    <tb:TaskbarIcon.TrayPopup>
        <Grid Background="White">
            <Grid.RowDefinitions>
                <RowDefinition Height="200"/>
                <RowDefinition Height="30"/>
            </Grid.RowDefinitions>
            <ScrollViewer Grid.Row="0">
                <ItemsControl ItemsSource="Binding NumberList, Mode=OneWay, UpdateSourceTrigger=PropertyChanged">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="200"/>
                                    <ColumnDefinition/>
                                </Grid.ColumnDefinitions>

                                <Label Grid.Column="0" Content="Binding Id, Mode=OneWay, UpdateSourceTrigger=PropertyChanged"/>
                                <Button Grid.Column="1" Content="Test" Command="Binding ElementName=trayMainStack, Path=DataContext.TestCommand"/> <!--Updated binding works!-->
                            </Grid>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <StackPanel Name="trayMainStack"/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                </ItemsControl>
            </ScrollViewer>

            <Button Grid.Row="1" Content="Test2" Command="Binding TestCommand"/> <!--This works-->
        </Grid>
    </tb:TaskbarIcon.TrayPopup>
</tb:TaskbarIcon>

【讨论】:

以上是关于WPF NotifyIcon 中 ItemsControl 中按钮的命令绑定的主要内容,如果未能解决你的问题,请参考以下文章

WPF 基础控件之托盘

当应用程序具有 NotifyIcon 时,任务计划程序给出 0xE0434352

WPF 托盘图标右键弹出的ContextMenu如何关闭

请问wpf中的GroupBox控件我想让他的Header位于右下角,注意是右下角,能实现吗?请详细说明,谢谢!

WPF 托盘闪烁

winform 不想自动弹出窗口, 最小化後图标要显示在右下角 (像杀毒软件那样),要怎麼做?