wpf 带有自定义下拉(弹出)模板等的组合框

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14533518/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 07:14:20  来源:igfitidea点击:

Combobox with custom dropdown(Popup) template and more

wpfwpf-controls

提问by Jayson Ragasa

I am having a problem hooking up some events in my custom dropdown or Popup template in my combobox.

我在我的组合框中的自定义下拉列表或弹出模板中连接某些事件时遇到问题。

This custom template by the way looks like the one in IE 10. Here's the picture enter image description hereI got the partial look (the one below is mine). But I'm having a problem deleting an item in history list. Below is my PART_Popup template

顺便说一下,这个自定义模板看起来像 IE 10 中的那个。这是在此处输入图片说明我得到的部分外观的图片 (下面是我的)。但是我在删除历史列表中的项目时遇到问题。下面是我的 PART_Popup 模板

<Popup x:Name="PART_Popup" AllowsTransparency="true" Grid.ColumnSpan="2" IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom">
    <Themes:SystemDropShadowChrome x:Name="Shdw" Color="Transparent" MinWidth="{Binding ActualWidth, ElementName=Placement}">
        <Border x:Name="DropDownBorder" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}">
            <!--<ScrollViewer>-->
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>

                <StackPanel>
                    <ItemsPresenter KeyboardNavigation.DirectionalNavigation="Contained" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>

                    <Border Padding="5">
                        <StackPanel>
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="Auto" />
                                    <ColumnDefinition Width="*" />
                                </Grid.ColumnDefinitions>
                                <TextBlock Text="History" Foreground="{StaticResource SeparatorLine}" />
                                <Border Height="2" Grid.Column="1" Margin="5,0,0,0" BorderBrush="{StaticResource SeparatorLine}" BorderThickness="0.5" />
                            </Grid>
                            <ListBox x:Name="listHistory"  BorderThickness="0" Margin="0" Padding="0" HorizontalContentAlignment="Stretch">
                                <ListBox.ItemTemplate>
                                    <DataTemplate>
                                        <Grid>
                                            <TextBlock Text="{Binding }" />
                                            <Button Grid.Column="1" HorizontalAlignment="Right" x:Name="btnDeleteHistoryItem" Content="r" FontFamily="Marlett" Style="{DynamicResource ButtonStyle}" Visibility="Hidden" Opacity="0.75" />
                                        </Grid>

                                        <DataTemplate.Triggers>
                                            <Trigger Property="IsMouseOver" Value="True">
                                                <Setter Property="Visibility" TargetName="btnDeleteHistoryItem" Value="Visible" />
                                            </Trigger>
                                        </DataTemplate.Triggers>
                                    </DataTemplate>
                                </ListBox.ItemTemplate>
                            </ListBox>
                    </StackPanel>
                    </Border>
                </StackPanel>

                <Border Grid.Row="1" BorderBrush="{StaticResource SeparatorLine}" BorderThickness="0,1,0,0" Padding="5" Height="30">
                    <Border.Background>
                        <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                            <GradientStop Color="#33000000" Offset="0"/>
                            <GradientStop Offset="1"/>
                            <GradientStop Offset="0.375"/>
                        </LinearGradientBrush>
                    </Border.Background>

                    <StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
                        <Button x:Name="btnClearHistory" Content=" Clear History " Style="{DynamicResource ButtonStyle}" />
                    </StackPanel>
                </Border>
            </Grid>
            <!--</ScrollViewer>-->
        </Border>
    </Themes:SystemDropShadowChrome>
</Popup>

alright, in the Listbox(listHistory)I have a button there called btnDeleteHistoryItemand I cannot hook it. It's returning a Null error in my code here

好的,在Listbox(listHistory) 中,我有一个名为btnDeleteHistoryItem的按钮,但我无法挂钩它。它在我的代码中返回 Null 错误

protected override void OnSourceInitialized(EventArgs e)
{
    ListBox lb = (ListBox)cbSearch.Template.FindName("listHistory", cbSearch);
    lb.ItemsSource = this.SearchHistory;
    lb.SelectionChanged += cbResults_SelectionChanged;

    Button btnDeleteHistoryItem = (Button)lb.Template.FindName("btnDeleteHistoryItem", lb);
    // if (btnDeleteHistoryItem != null)
    {
        btnDeleteHistoryItem.Click += DeleteHistoryItem_Click;
    }

    // or --------------

    Button btnDeleteHistoryItem = (Button)cbSearch.Template.FindName("btnDeleteHistoryItem", cbSearch);
    // if (btnDeleteHistoryItem != null)
    {
        btnDeleteHistoryItem.Click += DeleteHistoryItem_Click;
    }
}

Coding is a little classic here, so no MVVM implemented in hooking with events. So the problem is this Button btnDeleteHistoryItem = (Button)lb.Template.FindName("btnDeleteHistoryItem", lb);or Button btnDeleteHistoryItem = (Button)cbSearch.Template.FindName("btnDeleteHistoryItem", cbSearch);line where it cannot find that btnDeleteHistoryItem.

这里的编码有点经典,因此没有在挂钩事件中实现 MVVM。所以问题是这个Button btnDeleteHistoryItem = (Button)lb.Template.FindName("btnDeleteHistoryItem", lb); Button btnDeleteHistoryItem = (Button)cbSearch.Template.FindName("btnDeleteHistoryItem", cbSearch); 找不到 btnDeleteHistoryItem 的行。

How can I resolve this?

我该如何解决这个问题?

-- UPDATE --

- 更新 -

lb.Loaded += (a, b) =>
{
    Button btnDeleteHistoryItem = (Button)lb.Template.FindName("btnDeleteHistoryItem", lb);
    //if (btnDeleteHistoryItem != null)
    {
        btnDeleteHistoryItem.Click += DeleteHistoryItem_Click;
    }
};

doesn't work either

也不起作用

采纳答案by Brandon Sharp

Using a command will probably be the easiest solution here. You can hook a command up to your delete buttons and pass the current item in as the parameter. Here's a simple sample to illustrate.

在这里使用命令可能是最简单的解决方案。您可以将命令连接到删除按钮,并将当前项目作为参数传入。这是一个简单的示例来说明。

public partial class MainWindow : Window {
    public MainWindow() {
        InitializeComponent();
        SomeCommand = new MySampleCommand();

        cbo.Items.Add("Hello");
        cbo.Items.Add("Item 1");
        cbo.Items.Add("Another Item");
        cbo.Items.Add("Something else");
        cbo.Items.Add("Yet another item");
    }

    public MySampleCommand SomeCommand { get; set; }
}

public class MySampleCommand : ICommand {
    public bool CanExecute(object parameter) {
        return true;
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter) {
        MessageBox.Show(string.Format("You are trying to remove {0}", parameter.ToString()));
    }
}

Your combobox binding would look something like:

您的组合框绑定看起来像:

<Window x:Class="SOComboWithEmbeddedButton2.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Name="Window"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <DataTemplate x:Key="ListBoxItemTemplate">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding}" />
            <Button Command="{Binding SomeCommand, ElementName=Window}" CommandParameter="{Binding}" Content="Remove" />
        </StackPanel>
    </DataTemplate>
</Window.Resources>
<StackPanel>
    <ComboBox ItemTemplate="{StaticResource ListBoxItemTemplate}" x:Name="cbo" />
</StackPanel>

Just adjust the Command binding on the DataTemplate to point to the appropriate object that has an instance of your command object. Hope that helps!

只需调整 DataTemplate 上的 Command 绑定以指向具有命令对象实例的适当对象。希望有帮助!