在UserControl中更新ItemsControl(ComboBox)中的SelectedItem

时间:2011-10-26 19:10:48

标签: c# wpf user-controls combobox dependency-properties

在选择ComboBox中的任何项目之前,其SelectedItem为空,ComboBox本身在视觉上为空白。一旦选择了某些内容,用户似乎没有任何方式可以选择“缺少选择”(尽管可以通过在代码中将SelectedItem设置为null来完成。)

我的ComboBoxes绑定到我的对象的ObservableCollections。我不想在每个ObservableCollection的前面添加一个“特殊的”第一个类似null的对象。所以我借此机会学习一下编写UserControl。

问题是SelectedItem无法正常工作。也就是说,ComboBox很好地绑定到了支持ObservableCollection,但是从ComboBox中选择某些内容并不会更新它应该绑定的SelectedItem

我觉得我需要将UserControl中的ComboBox中的一些信息传递给某个地方。我是在正确的轨道上吗?我应该在谷歌上搜索什么?

C#:

public partial class ClearableComboBox : UserControl
{
    public ClearableComboBox()
    {
        InitializeComponent();
    }

    public IEnumerable ItemsSource
    {
        get { return (IEnumerable)base.GetValue(ItemsSourceProperty); }
        set { base.SetValue(ItemsSourceProperty, value); }
    }

    public static readonly DependencyProperty ItemsSourceProperty =
        DependencyProperty.Register("ItemsSource",
            typeof(IEnumerable),
            typeof(ClearableComboBox));

    public object SelectedItem
    {
        get { return (object)base.GetValue(SelectedItemProperty); }
        set { base.SetValue(SelectedItemProperty, value); }
    }

    public static readonly DependencyProperty SelectedItemProperty =
        DependencyProperty.Register("SelectedItem",
            typeof(object),
            typeof(ClearableComboBox));

    public string DisplayMemberPath
    {
        get { return (string)base.GetValue(DisplayMemberPathProperty); }
        set { base.SetValue(DisplayMemberPathProperty, value); }
    }

    public static readonly DependencyProperty DisplayMemberPathProperty =
        DependencyProperty.Register("DisplayMemberPath",
            typeof(string),
            typeof(ClearableComboBox));

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        comboBox.SelectedItem = null;
    }
}

XAML:

<UserControl x:Class="MyProj.ClearableComboBox"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             x:Name="root">
    <DockPanel>
        <Button DockPanel.Dock="Left" Click="Button_Click" ToolTip="Clear">
            <Image Source="pack://application:,,,/img/icons/silk/cross.png" Stretch="None" />
        </Button>
        <ComboBox
            Name="comboBox"
            ItemsSource="{Binding ElementName=root, Path=ItemsSource}"
            SelectedItem="{Binding ElementName=root, Path=SelectedItem}"
            DisplayMemberPath="{Binding ElementName=root, Path=DisplayMemberPath}" />
    </DockPanel>
</UserControl>

用法:

<wpfControl:ClearableComboBox ItemsSource="{Binding Path=Things}"
                              DisplayMemberPath="SomeProperty"
                              SelectedItem="{Binding Path=SelectedThing}" />

// Picking a Thing doesn't update SelectedThing :(

3 个答案:

答案 0 :(得分:1)

因为组合框来自Selector类,而后者又来自ItemsControl。因此,通过从UserControl派生,您将使用Selector类的属性来解除组合框,这可能会在内部为您处理Selection事物。所以,我建议而不是从UserControl派生它,你应该从这样的Combobox派生它 -

public partial class ClearableComboBox : ComboBox

因此,您可以通过这种方式覆盖类中的ItemsSource,DisplayMemberPath等,因为它已经存在于ComboBox类中。您可以随时进一步扩展您的类以提供附加功能,在您的情况下,在某些按钮单击时将SelectedItem设置为null。希望这是你想要的......

编辑(自定义控制)

创建自定义控件是您的答案,如果您不了解它就开始使用,请先查看此内容 - http://www.wpftutorial.net/HowToCreateACustomControl.html

当您创建自定义控件时,请说CustomControl1,将Generic.xaml文件中的CustomControl1模板替换为此文件 -

<ControlTemplate TargetType="{x:Type local:CustomControl1}">
    <Border Background="{TemplateBinding Background}"
            BorderBrush="{TemplateBinding BorderBrush}"
            BorderThickness="{TemplateBinding BorderThickness}">
              <DockPanel>
                 <Button Name="btn" DockPanel.Dock="Left" ToolTip="Clear" Width="20">
                    <Image Source="pack://application:,,,/img/icons/silk/cross.png" Stretch="None" />
                </Button>
                <ComboBox Name="comboBox"
                          ItemsSource="{TemplateBinding ItemsSource}"
                          SelectedItem="{TemplateBinding SelectedItem}"
                          DisplayMemberPath="{TemplateBinding DisplayMemberPath}" />
              </DockPanel>
     </Border>
</ControlTemplate>

默认情况下,您的CustomControl1课程将来自Control。将其替换为从类ComboBox派生,以便您不再像这样重新声明DP并将其复制粘贴到那里 -

public class CustomControl1 : ComboBox
{
        private Button clearButton;
        private ComboBox comboBox;

        static CustomControl1()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl1), new FrameworkPropertyMetadata(typeof(CustomControl1)));
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            clearButton = GetTemplateChild("btn") as Button;
            comboBox = GetTemplateChild("comboBox") as ComboBox;
            clearButton.Click += new RoutedEventHandler(clearButton_Click);
        }

        private void clearButton_Click(object sender, RoutedEventArgs e)
        {
            comboBox.SelectedItem = null;
        }
}

现在,您的CustomControl1类已准备好在您的其他xaml文件中使用 -

<local:CustomControl1 ItemsSource="{Binding YourSource}"
                      SelectedItem="{Binding YourSelectedItem}"
                      Height="50" Width="200"/>

答案 1 :(得分:0)

我选择在组合框上处理按键事件并按下转义按键以清除组合框的SelectedItem

答案 2 :(得分:0)

我认为有更好的方法,为ComboBox开发一个包装器/装饰器,在ComboBox旁边添加一个按钮,然后在点击时擦除选择。

相关问题