Combobox with custom dropdown(Popup) template and more

左心房为你撑大大i 提交于 2019-12-11 05:52:37

问题


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

I 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
<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 btnDeleteHistoryItem and I cannot hook it. It's returning a Null error in my code here

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.

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


回答1:


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!



来源:https://stackoverflow.com/questions/14533518/combobox-with-custom-dropdownpopup-template-and-more

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!