WPF将标头添加到自定义组合框

时间:2016-10-13 09:04:55

标签: c# wpf combobox

我有一个自定义的ComboBox,每个项目(收藏夹而不是收藏夹)是一个Label + Button,然后最后一个项目只有一个按钮来加载所有元素。现在我想添加标题作为第一项,即“收藏夹”。

现在我有:

<ComboBox 
        x:Name="ComboBoxBtn" 
        VerticalAlignment="Top" 
        HorizontalAlignment="Left" 
        Margin="0,0,0,-1" 
        Width="300" 
        ItemsSource="{Binding Source, RelativeSource={RelativeSource AncestorType=UserControl}}"
        SelectedItem="{Binding Path=Selected, Mode=TwoWay, RelativeSource={RelativeSource AncestorType=UserControl}}"
        IsSynchronizedWithCurrentItem="True">        
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <Grid Name="PART_GRID">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="3*" />
                        <ColumnDefinition Width="Auto" />
                    </Grid.ColumnDefinitions>
                    <Label
                        Content="{Binding}"
                       Width="250" Visibility="{Binding Path=., Converter={StaticResource elementToVisibilityConverter}}" />
                    <Button Name="PART_BUTTON"
                        Grid.Column="1"
                        Content="+"
                        Command="{Binding AddCommandButton, ElementName=root}"
                        CommandParameter="{Binding}"
                        Visibility="{Binding Path=., Converter={StaticResource elementToVisibilityConverter}}"/>
                    <Button Content="Carregar Todos" Margin="5,5"
                                    Command="{Binding LoadAllCommandButton, ElementName=root}"
                                    CommandParameter="{Binding ElementName=root, Path=FavoriteType}"
                                    Visibility="{Binding Path=.,Converter={StaticResource elementToVisibilityForAddConverter}}"/>
                </Grid>
                <DataTemplate.Triggers>
                    <DataTrigger Binding="{Binding Favorite}"
                             Value="True">
                        <Setter TargetName="PART_GRID"
                            Property="Background"
                            Value="#FFE6E6FA" />
                        <Setter TargetName="PART_BUTTON"
                            Property="Content"
                            Value="-" />
                        <Setter TargetName="PART_BUTTON"
                            Property="Command"
                            Value="{Binding RemoveCommandButton, ElementName=root}" />
                    </DataTrigger>
                </DataTemplate.Triggers>
            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox>

1 个答案:

答案 0 :(得分:1)

我更喜欢不同的方法,我认为这种方法更容易,也更干净:

我创建了一个空接口IDrawable。 我需要放在组合框内的所有类都应继承自IDrawable 我创造了这些:
MyLabel:

public class MyLabel : IDrawable
{
    public string text { get; set; }
    public MyLabel()
    {
        this.text = "MYTEXT";
    }
}

<强> myButton的:

public class MyButton : IDrawable
{
    public string text { get; set; }
    public MyButton()
    {
        this.text = "MYNBUTTON";
    }
}

<强> MyLabelButton:     公共类MyLabelButton:IDrawable     {         public string labelText {get;组; }         public string buttonText {get;组; }

    public MyLabelButton()
    {
        labelText = "labelText";
        buttonText = "buttonText";
    }
}

这里是xaml

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:me="clr-namespace:WpfApplication1">
    <Window.Resources>
        <DataTemplate DataType="{x:Type me:MyButton}">
            <Button Content="{Binding text}" />
        </DataTemplate>
        <DataTemplate DataType="{x:Type me:MyLabel}">
            <TextBlock Text="{Binding text}"/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type me:MyLabelButton}">
            <StackPanel Orientation="Horizontal">
                <Label Content="{Binding labelText}"/>
                <Button Content="{Binding buttonText}"/>
            </StackPanel>
        </DataTemplate>
    </Window.Resources>
    <Grid Name="MyGrid">
        <ComboBox Name="MyCombo" ItemsSource="{Binding list}" SelectedItem="{Binding sel}" PreviewMouseLeftButtonUp="ComboBox_PreviewMouseLeftButtonUp"/>
    </Grid>
</Window>

和codebehind:

public partial class MainWindow : Window
    {
        private IDrawable clicked;

        public ObservableCollection<IDrawable> list { get; set; }
        public IDrawable sel { get; set; }

        public MainWindow()
        {
            InitializeComponent();
            list = new ObservableCollection<IDrawable>();
            list.Add(new MyLabel());
            list.Add(new MyLabelButton());
            list.Add(new MyButton());
            this.DataContext = this;
        }

        private void ComboBox_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            Point pt = e.GetPosition(MyGrid);

            clicked = null;
            VisualTreeHelper.HitTest(
                MyGrid,
                null,
                new HitTestResultCallback(ResultCallback),
                new PointHitTestParameters(pt));


            if (clicked != null)
            {
                ((ComboBox)sender).IsDropDownOpen = false;

                //do something
            }
        }

        private HitTestResultBehavior ResultCallback(HitTestResult result)
        {
            DependencyObject parentObject = VisualTreeHelper.GetParent(result.VisualHit);

            if (parentObject == null)
                return HitTestResultBehavior.Continue;

            var v = parentObject as Button;

            if (v == null)
                return HitTestResultBehavior.Continue;

            if (v.DataContext != null && v.DataContext is IDrawable)
            {
                clicked = (IDrawable)v.DataContext;
                return HitTestResultBehavior.Stop;
            }
            return HitTestResultBehavior.Continue;
        }
    }

结果为this

你可以看到我有标准的组合框和自定义元素。我觉得它更好。在代码隐藏中,您可以处理所有内容,例如无法选择第一个标签,调用与按钮关联的命令,是否按下按钮等等。

ComboBox_PreviewMouseLeftButtonUp我处理了所选项目的点击,以防您在按下所选按钮时想要执行特定操作,而不显示下拉菜单。

这个例子非常简单,你需要更多地定制它并在任何地方使用MVVM 目前你可以按下dropDown菜单中的按钮,如果没有选择该按钮,你可能会想要禁用点击。

修改

ComboBox_PreviewMouseLeftButtonUp应该是这样的:

private void ComboBox_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            Point pt = e.GetPosition((ComboBox)sender);

            clicked = null;
            VisualTreeHelper.HitTest(
                (ComboBox)sender,
                null,
                new HitTestResultCallback(ResultCallback),
                new PointHitTestParameters(pt));


            if (clicked != null)
            {
                ((ComboBox)sender).IsDropDownOpen = false;

                //do something
            }
        }

(将Mygrid替换为(ComboBox)sender