Labeled ComboBox in Windows 10 Universal App

a 夏天 提交于 2019-12-11 12:04:07

问题


similar to my Labeled TextBox, which issues are resolved in:

Labeled TextBox in Windows Universal App

I got two issues in my Labeled Combobox, but first the Code:

Generic.xaml:

<Style TargetType="template:LabeledComboBox">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="template:LabeledComboBox">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="*" />
                        <RowDefinition Height="*" />
                    </Grid.RowDefinitions>
                    <TextBlock Text="{TemplateBinding Label}" FontWeight="Bold" VerticalAlignment="Center" Margin="10,0" />
                    <ComboBox x:Name="PART_ComboBox" ItemsSource="{TemplateBinding ItemsSource}" SelectedIndex="{TemplateBinding SelectedIndex}" SelectedValue="{TemplateBinding SelectedValue}" SelectedValuePath="{TemplateBinding SelectedValuePath}" DisplayMemberPath="{TemplateBinding DisplayMemberPath}" VerticalAlignment="Center" Margin="20,0,10,0" Grid.Row="1" />
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

LabeledComboBox.cs:

[TemplatePart(Name = "PART_ComboBox", Type = typeof(ComboBox))]
public sealed class LabeledComboBox : Control, IParameterReturnable
{
    public static readonly DependencyProperty LabelProperty = DependencyProperty.Register("Label", typeof(string), typeof(LabeledComboBox), new PropertyMetadata(""));
    public string Label
    {
        get { return GetValue(LabelProperty).ToString(); }
        set { SetValue(LabelProperty, value); }
    }

    public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(object), typeof(LabeledComboBox), new PropertyMetadata(null));
    public object ItemsSource
    {
        get { return GetValue(ItemsSourceProperty); }
        set { SetValue(ItemsSourceProperty, value); }
    }

    public static readonly DependencyProperty SelectedIndexProperty = DependencyProperty.Register("SelectedIndex", typeof(int), typeof(LabeledComboBox), new PropertyMetadata(default(int)));
    public int SelectedIndex
    {
        get { return (int) GetValue(SelectedIndexProperty); }
        set { SetValue(SelectedIndexProperty, value); }
    }

    public static readonly DependencyProperty SelectedValueProperty = DependencyProperty.Register("SelectedValue", typeof(object), typeof(LabeledComboBox), new PropertyMetadata(null));
    public object SelectedValue
    {
        get { return GetValue(SelectedValueProperty); }
        set { SetValue(SelectedValueProperty, value); }
    }

    public static readonly DependencyProperty SelectedValuePathProperty = DependencyProperty.Register("SelectedValuePath", typeof(string), typeof(LabeledComboBox), new PropertyMetadata(default(string)));
    public string SelectedValuePath
    {
        get { return GetValue(SelectedValuePathProperty).ToString(); }
        set { SetValue(SelectedValuePathProperty, value); }
    }

    public static readonly DependencyProperty DisplayMemberPathProperty = DependencyProperty.Register("DisplayMemberPath", typeof(string), typeof(LabeledComboBox), new PropertyMetadata(default(string)));
    public string DisplayMemberPath
    {
        get { return GetValue(DisplayMemberPathProperty).ToString(); }
        set { SetValue(DisplayMemberPathProperty, value); }
    }

    private ComboBox _comboBox;

    public LabeledComboBox()
    {
        this.DefaultStyleKey = typeof(LabeledComboBox);
    }

    public LabeledComboBox(List<Parameter> parameterList)
    {
        this.Label = parameterList[0].DisplayName ?? "";
        this.ItemsSource = parameterList;
        this.SelectedValuePath = "DefaultValue";
        this.DisplayMemberPath = "DefaultValue";
        this.SelectedIndex = 0;
        this.DefaultStyleKey = typeof(LabeledComboBox);
    }

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

        _comboBox = GetTemplateChild("PART_ComboBox") as ComboBox;

        if (_comboBox != null)
        {
            _comboBox.SelectionChanged += OnComboBoxSelectionChanged;
            if (_comboBox.Items != null)
            {
                this.SelectedIndex = 0;
                _comboBox.SelectedValue = _comboBox.Items[this.SelectedIndex];
            }
        }
    }

    private void OnComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        this.SelectedValue = _comboBox.SelectedValue;
    }

    public string GetKey()
    {
        return Label;
    }

    public string GetValue()
    {
        return SelectedValue.ToString();
    }

}

It will be called in two different ways:

Dynamically in C#:

stackPanel.Add(new LabeledComboBox(parameterList));

Static in Xaml:

<templates:LabeledComboBox Label="Kategorien:" ItemsSource="{Binding ElementName=pageRoot, Path=FeedCategories}" DisplayMemberPath="Name" SelectedValuePath="Name" />

As I said before I got two issues with it:

  1. How can I bind the SelectionChangedEvent to access it in Xaml || C#
  2. As you can see, I try to preselect the first Item, which does not work and I don't know how to do it right

Thank you very much for all helpful and well meant answers in advance!


回答1:


Instead of creating a custom control and recreating all needed dependency properties, I would suggest you use the Header and HeaderTemplate properties of the built in ComboBox, which will be displayed, just like in your LabeledComboBox, above the selection menu. Additionally the SelectionChanged event will be available.

So the usage in XAML would look like the following:

    <ComboBox
        DisplayMemberPath="Name"
        Header="Kategorien:"
        ItemsSource="{Binding ElementName=pageRoot, Path=FeedCategories}"
        SelectedValuePath="Name"
        SelectionChanged="OnSelectionChanged">
        <ComboBox.HeaderTemplate>
            <DataTemplate>
                <TextBlock
                    Margin="10,0"
                    VerticalAlignment="Center"
                    FontWeight="Bold"
                    Text="{Binding}" />
            </DataTemplate>
        </ComboBox.HeaderTemplate>
    </ComboBox>

But if you don't want to use the above method, to expose the selection changed event in your LabeledComboBox, add the following code:

    private void OnComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        this.SelectedValue = _comboBox.SelectedValue;
        this.RaiseSelectionChanged(e);
    }

    public event EventHandler<SelectionChangedEventArgs> SelectionChanged;

    private void RaiseSelectionChanged(SelectionChangedEventArgs args)
    {
        if (SelectionChanged != null)
        {
            SelectionChanged(this, args);
        }
    }

Then you can use the created SelectionChanged event from XAML.



来源:https://stackoverflow.com/questions/32521254/labeled-combobox-in-windows-10-universal-app

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