Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Effiecient way to do static ComboBox in WPF

I have a static ComboBox in my wpf applicaiton, that loads space followed by 0-9. I have the following code it does the job what I need, but I dont feel its a great way to do. Any suggestion or opinion will be appreciated.

Test.xaml

<ComboBox Name="cbImportance" 
          Text="{Binding SelectedStory.ImportanceList, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=True, NotifyOnValidationError=True, ValidatesOnDataErrors=True}" Validation.ErrorTemplate="{StaticResource ErrorTemplate}" 
          Loaded="cbImportance_Loaded"
          Grid.Column="1"
          d:LayoutOverrides="Height" 
          Grid.ColumnSpan="2" 
          HorizontalAlignment="Stretch"
          Margin="0,9" 
          SelectionChanged="cbImportance_SelectionChanged" />

Test.xaml.cs

private void cbImportance_Loaded(object sender, RoutedEventArgs e)
{
    List<string> data = new List<string>();
    data.Add("");
    data.Add("0");
    data.Add("1");
    data.Add("2");
    data.Add("3");
    data.Add("4");
    data.Add("5");
    data.Add("6");
    data.Add("7");
    data.Add("8");
    data.Add("9");

    // ... Get the ComboBox reference.
    var cbImportance = sender as ComboBox;

    // ... Assign the ItemsSource to the List.
    cbImportance.ItemsSource = data;

    // ... Make the first item selected.
    cbImportance.SelectedIndex = 0;
}

Which one is the efficient way to load the static value in to ComboBox:

  1. Through XAML (suggested by Anatoliy Nikolaev)
  2. xaml.cs (Like Above)
  3. Create constructor in ViewModel and load the static value back to ComboBox?
like image 763
Usher Avatar asked Mar 05 '14 05:03

Usher


2 Answers

In WPF has support for arrays of objects in XAML through a markup extension. This corresponds to the x:ArrayExtension XAML type MSDN.

You can do this:

<Window ...
        xmlns:sys="clr-namespace:System;assembly=mscorlib">

<x:Array x:Key="ParametersArray" Type="{x:Type sys:String}">
    <sys:String>0</sys:String>
    <sys:String>1</sys:String>
    <sys:String>2</sys:String>
    <sys:String>3</sys:String>
    ...
</x:Array>

<ComboBox Name="ParameterComboBox"
          SelectedIndex="0"
          ItemsSource="{StaticResource ParametersArray}" ... />

For setting empty string in x:Array use a static member:

<x:Array x:Key="ParametersArray" Type="{x:Type sys:String}">
    <x:Static Member="sys:String.Empty" />
    <sys:String>0</sys:String>
    <sys:String>1</sys:String>
    <sys:String>2</sys:String>
    <sys:String>3</sys:String>
    ...
</x:Array>

If you need to define a static ComboBox with numbers Int32 type, it can be even shorter:

<Window.Resources>
    <Int32Collection x:Key="Parameters">0,1,2,3,4,5,6,7,8,9</Int32Collection>
</Window.Resources>

<ComboBox Width="100" 
          Height="30" 
          ItemsSource="{StaticResource Parameters}" />

Or like this:

<ComboBox Width="100" Height="30">
    <ComboBox.ItemsSource>
        <Int32Collection>0,1,2,3,4,5,6,7,8,9</Int32Collection>
    </ComboBox.ItemsSource>
</ComboBox>
like image 177
Anatoliy Nikolaev Avatar answered Sep 22 '22 20:09

Anatoliy Nikolaev


There are many ways to use enumerable object as ItemsSource, based on {StaticResource} or {Binding} or other dependancy property. Binding is preferred way, because it meets MVVM approach, wich is recommended for WPF apps.

MVVM way

With binding we have list of values as property of ViewModel object, which is set as DataContext in terms of WPF. So, here is binding example:

ViewModel:

public class MyViewModel : INotifyPropertyChanged
{
    public ObservableCollection<SomeObject> Items
    {
        get { /* ... */ }
    }
    public SomeObject SelectedItem
    {
        get { /* ... */ }
        set { /* ... */ }
    }
}

View:

<Window
    x:Class="Project1.MainWindow">
    <ComboBox
        ItemsSource={Binding Items}
        SelectedItem={Binding SelectedItem} />
</Window>

String array as static resource

This solution was finely illustrated in previous answer by @AnatoliyNikolaev.

XmlDataProvider

Sometimes you have to operate on complex values which have visible title. Putting it in ViewModel is senseless - better use XAML features. That's what it looks like:

<Window>
    <Window.Resources>
        <XmlDataProvider x:Key="YesNo" XPath="Items">
            <x:XData>
                <Items xmlns="">
                    <Item Header="Yes" Value="1"/>
                    <Item Header="No" Value="0"/>
                </Items>
            </x:XData>
        </XmlDataProvider>
    </Window.Resources>
    <Grid>
        <ComboBox
            ItemsSource="{Binding Source={StaticResource YesNo},XPath=*,Mode=OneTime}"
            SelectedValue="{Binding Value,UpdateSourceTrigger=PropertyChanged}"
            SelectedValuePath="@Value"
            DisplayMemberPath="@Header">
    </Grid>
</Window>
like image 37
oxfn Avatar answered Sep 24 '22 20:09

oxfn