ViewMakerで生成するWPF/Silverlightコントロール(3)ComboBox編

今回はComboBoxでこれも業務アプリではよく使うコントロールです。

ComboBoxコントロール

WPFSilverlight両方ともComboBoxは標準で含まれていますがSilverlightは残念ながら編集可能にできません。ViewMakerでは編集可能なComboBoxをAutoCompleteBoxで代用しています。*1
ComboBoxは選択した値をバインドするプロパティに対して設定し、一覧用データなどを表すプロパティを合わせて指定します。ViewMakerで指定可能な項目は以下のプロパティです。

    1. ItemsSource(一覧用のデータソース)
    2. SelectedValuePath(ItemsSourceで選択されたデータの値を示すプロパティのパス)
    3. DisplayMemberPath(ItemsSourceの各アイテムの表示に利用するプロパティのパス)
    4. IsEditable(編集可能か?)
    5. SelectionChangedCommand(選択データ変更時に実行するコマンド)

ビヘイビアとして選択データ変更時のコマンド実行を追加しました。SelectionChangedの代わりにSelectedItemやSelectedValueにバインドしているPropertyChangedで代用できそうですが、バインド時ソース更新とコマンド実行は処理の仕組みの違いや意味的な違いもあるため代用は避けるべきと考えて用意しています。

WPFサンプルイメージとXAMLコード

          <ComboBox Name="ComboBox1" SelectedItem="{Binding Path=ComboBox1, Mode=TwoWay, ValidatesOnExceptions=True, ValidatesOnDataErrors=True}"
		 ItemsSource="{Binding Path=ItemSource1,Mode=OneWay}" vg:SelectionChangedBehavior.Command="{Binding Path=SelectionChangedCommand1, 
		Mode=OneWay}" VerticalAlignment="Center" xmlns:vg="clr-namespace:ViewMaker.Core.Wpf;assembly=ViewMaker.Core" />

          <ComboBox Name="ComboBox2" SelectedValue="{Binding Path=ComboBox2, Mode=TwoWay, ValidatesOnExceptions=True, ValidatesOnDataErrors=True}"
 		SelectedValuePath="Key" DisplayMemberPath="Value" ItemsSource="{Binding Path=ItemSource2,Mode=OneWay}" Width="250" Foreground="Blue"
		 Background="Azure" vg:SelectionChangedBehavior.Command="{Binding Path=SelectionChangedCommand2, Mode=OneWay}" 
		VerticalAlignment="Center" HorizontalAlignment="Left" xmlns:vg="clr-namespace:ViewMaker.Core.Wpf;assembly=ViewMaker.Core">
            <ComboBox.Resources>
              <Style TargetType="{x:Type ComboBoxItem}">
                <Setter Property="Foreground" Value="Blue" />
                <Setter Property="Background" Value="Azure" />
              </Style>
            </ComboBox.Resources>
          </ComboBox>

          <ComboBox Name="ComboBox3" Text="{Binding Path=ComboBox3, Mode=TwoWay, ValidatesOnExceptions=True, ValidatesOnDataErrors=True}" 
		IsEditable="True" ItemsSource="{Binding Path=ItemSource1,Mode=OneWay}" Width="250" Foreground="Blue" Background="Azure" 
		VerticalAlignment="Center" HorizontalAlignment="Left">
            <ComboBox.Resources>
              <Style TargetType="{x:Type ComboBoxItem}">
                <Setter Property="Foreground" Value="Blue" />
                <Setter Property="Background" Value="Azure" />
              </Style>
            </ComboBox.Resources>
          </ComboBox>

          <ComboBox Name="ComboBox4" SelectedItem="{Binding Path=ComboBox4, Mode=TwoWay, ValidatesOnExceptions=True, 
		ValidatesOnDataErrors=True}" VerticalAlignment="Center">
            <ComboBox.Items>
              <system:String>one</system:String>
              <system:String>two</system:String>
              <system:String>three</system:String>
            </ComboBox.Items>
          </ComboBox>

SilverlightサンプルイメージとXAMLコード

          <ComboBox Name="ComboBox1" ItemsSource="{Binding Path=ItemSource1,Mode=OneWay}" SelectedItem="{Binding Path=ComboBox1, Mode=TwoWay, 
		ValidatesOnExceptions=True, ValidatesOnDataErrors=True}" VerticalAlignment="Center">
            <i:Interaction.Behaviors>
              <vg:SelectionChangedBehavior vg:Command="{Binding Path=SelectionChangedCommand1, Mode=OneWay}" 
		xmlns:vg="clr-namespace:ViewMaker.Core.Silverlight;assembly=SilverlightViewMaker.Core" />
            </i:Interaction.Behaviors>
          </ComboBox>

          <ComboBox Name="ComboBox2" ItemsSource="{Binding Path=ItemSource2,Mode=OneWay}" SelectedValue="{Binding Path=ComboBox2, Mode=TwoWay, 
		ValidatesOnExceptions=True, ValidatesOnDataErrors=True}" SelectedValuePath="Key" DisplayMemberPath="Value" Width="250" 
		Foreground="Blue" Background="Azure" VerticalAlignment="Center" HorizontalAlignment="Left">
            <i:Interaction.Behaviors>
              <vg:SelectionChangedBehavior vg:Command="{Binding Path=SelectionChangedCommand2, Mode=OneWay}" 
		xmlns:vg="clr-namespace:ViewMaker.Core.Silverlight;assembly=SilverlightViewMaker.Core" />
            </i:Interaction.Behaviors>
          </ComboBox>

          <input:AutoCompleteBox Name="ComboBox3" ItemsSource="{Binding Path=ItemSource1,Mode=OneWay}" Text="{Binding Path=ComboBox3, Mode=TwoWay, 
		ValidatesOnExceptions=True, ValidatesOnDataErrors=True}" MinimumPrefixLength="0" FilterMode="None" Width="250" Foreground="Blue" 
		Background="Azure" VerticalAlignment="Center" HorizontalAlignment="Left" />

          <ComboBox Name="ComboBox4" SelectedItem="{Binding Path=ComboBox4, Mode=TwoWay, ValidatesOnExceptions=True, ValidatesOnDataErrors=True}" 
		VerticalAlignment="Center">
            <ComboBox.Items>
              <String xmlns="clr-namespace:System;assembly=mscorlib">one</String>
              <String xmlns="clr-namespace:System;assembly=mscorlib">two</String>
              <String xmlns="clr-namespace:System;assembly=mscorlib">three</String>
            </ComboBox.Items>
          </ComboBox>

ViewModelコード

        [View(ViewControlType.StackPanel)]
        [ViewProperty(StackPanelViewControl.Properties.HeaderPosition, LayoutHeaderPosition.Hidden)]
        [ViewLayoutGeneratorProvider("Generate")]
        public class ComboBoxSample : ViewModel
        {
            [View(ViewControlType.ComboBox)]
            [ViewProperty(ComboBoxViewControl.Properties.ItemsSource, "ItemSource1")]
            [ViewProperty(ComboBoxViewControl.Properties.SelectionChangedCommand, "SelectionChangedCommand1")]
            public string ComboBox1 { get; set; }

            [View(ViewControlType.Label)]
            [Display(Name = "Seleced Value")]
            [ViewProperty(LabelViewControl.Properties.HeaderPosition, LayoutHeaderPosition.Left)]
            public string ComboBox1Value { get; set; }

            [View(ViewControlType.ComboBox)]
            [ViewProperty(ComboBoxViewControl.Properties.ItemsSource, "ItemSource2")]
            [ViewProperty(ComboBoxViewControl.Properties.DisplayMemberPath, "Value")]
            [ViewProperty(ComboBoxViewControl.Properties.SelectedValuePath, "Key")]
            [ViewProperty(TextBoxViewControl.Properties.Foreground, "Blue")]
            [ViewProperty(TextBoxViewControl.Properties.Background, "Azure")]
            [ViewProperty(TextBoxViewControl.Properties.Width, 250)]
            [ViewProperty(ComboBoxViewControl.Properties.SelectionChangedCommand, "SelectionChangedCommand2")]
            public string ComboBox2 { get; set; }

            [View(ViewControlType.Label)]
            [Display(Name = "Seleced Value")]
            [ViewProperty(LabelViewControl.Properties.HeaderPosition, LayoutHeaderPosition.Left)]
            public int ComboBox2Value { get; set; }

            [View(ViewControlType.ComboBox)]
            [ViewProperty(ComboBoxViewControl.Properties.ItemsSource, "ItemSource1")]
            [ViewProperty(ComboBoxViewControl.Properties.IsEditable, true)]
            [ViewProperty(TextBoxViewControl.Properties.Foreground, "Blue")]
            [ViewProperty(TextBoxViewControl.Properties.Background, "Azure")]
            [ViewProperty(TextBoxViewControl.Properties.Width, 250)]
            public string ComboBox3 { get; set; }


            [View(ViewControlType.ComboBox)]
            public string ComboBox4 { get; set; }

            [Browsable(false)]
            public List<string> ItemSource1
            {
                get { return new List<string>(new string[] {"ONE","TWO","THREE"}); }
            }

            [Browsable(false)]
            public Dictionary<int, string> ItemSource2
            {
                get 
                {
                    var dict = new Dictionary<int, string>();
                    dict.Add(1, "One");
                    dict.Add(2, "Two");
                    dict.Add(3, "Three");
                    return dict;
                }
            }

            [Browsable(false)]
            public ICommand SelectionChangedCommand1 { get { return CreateCommand(SelectionChanged1); } }
            private void SelectionChanged1(object x)
            {
                var data = (object[])x;
                ComboBox1Value = (string)data[0];
                OnPropertyChanged("ComboBox1Value");
            }
            [Browsable(false)]
            public ICommand SelectionChangedCommand2 { get { return CreateCommand(SelectionChanged2); } }
            private void SelectionChanged2(object x)
            {
                var data = (object[])x;
                ComboBox2Value = ((KeyValuePair<int, string>)data[0]).Key;
                OnPropertyChanged("ComboBox2Value");
            }

            public static ViewLayoutItem Generate()
            {
                var svc = ServiceLocator.GetService<IViewLayoutGenerator>();
                var layout = svc.Generate(typeof(ComboBoxSample), LayoutGenerateFlag.All & ~LayoutGenerateFlag.StaticProvider);

                var items = layout.FindChild("ComboBox4").GetControl<ComboBoxViewControl>().ItemsList;
                items.Add("one");
                items.Add("two");
                items.Add("three");
                return layout;
            }
        }

*1:AutoCompleteBoxはSDKに含まれています