7997

Labeled ComboBox in Windows 10 Universal App

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:

<strong>Generic.xaml</strong>:

<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>

<strong>LabeledComboBox.cs</strong>:

[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:

<strong>Dynamically in C#</strong>:

stackPanel.Add(new LabeledComboBox(parameterList));

<strong>Static in Xaml</strong>:

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

As I said before I got two issues with it:

<ol><li>How can I bind the SelectionChangedEvent to access it in Xaml || C#</li> <li>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</li> </ol>

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

Answer1:

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.

Recommend

  • Dependent properties
  • listbox is not updated by dependency property observablecollection
  • Binding a ObservableCollection to IEnumerable of a custom control
  • Binding to ColumnDefinition.ActualWidth returns 0
  • VisualStateManager fails to start animation on UserControl
  • Binding to ColumnDefinition.ActualWidth returns 0
  • Labeled ComboBox in Windows 10 Universal App
  • I want to handle a clickbutton event from another page
  • binding to dynamic resource in ItemsControl on the ItemsSource Property
  • Join 2 tables on dynamically changing column
  • Custom WPF Binding
  • C# WPF Datagrid doesn't dynamically sort on data update
  • HostingEnvironment.QueueBackgroundWorkItem uses ASP.Net thread pool or another thread pool?
  • Exception occurs when button clicked inside my custom control
  • Data Type of Columns in a List - R
  • Async Controllers in ASP.NET MVC
  • Singleton Alternative - is it equivalent?
  • Should a C# struct have only read-only properties
  • How to edit a Word document that opens in read-mode in VBA
  • How to write string.Contains(someText) in expression Tree
  • DependencyObject.AssociatedObject is always null
  • when does setTimeout start executing in a inline
  • How do I register classes by both interface and namespace with Windsor?
  • How to getText() from the input field of an angularjs Application
  • Disable Kendo Autocomplete
  • QLineEdit password safety
  • Nant, Vault & Windows Integrated Authentication
  • Bug in WPF DataGrid
  • Validaiting emails with Net.Mail MailAddress
  • sending/ receiving email in Java
  • jQuery tmpl and DataLink beta
  • How can I estimate amount of memory left with calling System.gc()?
  • Cannot Parse HTML Data Using Android / JSOUP
  • JTable with a ScrollPane misbehaving
  • Java static initializers and reflection
  • unknown Exception android
  • Observable and ngFor in Angular 2
  • failed to connect to specific WiFi in android programmatically
  • Unable to use reactive element in my shiny app
  • How can I use threading to 'tick' a timer to be accessed by other threads?