2017-09-08 16 views
-2

実行時にビューに追加されるコンボボックスコントロールを動的に作成しています。ComboBoxはSelectedItemを更新しません

var comboBox = new ComboBox(); 
comboBox.Height = 21; 
comboBox.Width = 75; 
var margin = comboBox.Margin; 
margin.Right += 5; 
comboBox.Margin = margin; 
comboBox.SetBinding(ItemsControl.ItemsSourceProperty, new Binding($"SearchDescriptor.SelectedFilter.FilterControls[{InputPosition}].Conditions")); 
comboBox.IsSynchronizedWithCurrentItem = true; 
comboBox.SelectedValuePath = "ConditionOperator"; 
comboBox.DisplayMemberPath = "Text"; 
comboBox.SetBinding(Selector.SelectedItemProperty, new Binding($"SearchDescriptor.SelectedFilter.FilterControls[{InputPosition}].SelectedCondition")); 
Grid.SetColumn(comboBox, 1); 
return comboBox; 

これはコンボボックスコントロールを生成するコードです。コントロール自体は、このプロパティは、コントロールオブジェクトのコレクションを保持して、選択したフィルタ特性を持つ

SearchDescriptor 

という名前のプロパティを持ついくつかのビューモデルにDataContextのセットを持つビューに置かれます。これらのコントロールオブジェクトは、コントロールの生成とバインディングの設定を行います。

最初はバインディングが機能しますが、コンボボックスからオプションを選択すると、バインドされているプロパティは更新されません。 パスが明らかに正しくないので、これは奇妙です。そうでなければ、最初はプロパティをバインドしません。

私はこの問題に遠隔で関連しているすべての質問を見てきたが、すべてを試してみたが役に立たなかった。

のSelectedItemは、タイプ条件であり、クラスは次のようになりますSelectedConditionという名前のプロパティにバインドされています

public struct Condition 
{ 
    public ConditionOperator ConditionOperator { get; } 
    public string Text { get; } 
    public Condition(ConditionOperator conditionOperator, string text) 
    { 
     ConditionOperator = conditionOperator; 
     Text = text; 
    } 
} 

編集 財産SelectedConditionに

public class SearchDescriptorFilterControl 
{ 
    private SearchDescriptorFilter m_filter; 
    private IEnumerable<ConditionOperator> m_choosableConditions; 
    private object m_value; 

    public SearchDescriptorFilter Filter 
    { 
     get 
     { 
      return m_filter; 
     } 
     set 
     { 
      if (m_filter != null) 
       throw new Exception("Filter can be set only once."); 
      m_filter = value; 
     } 
    } 

    public string Label { get; set; } 

    public double? LabelWidth { get; set; } 

    public HorizontalAlignment LabelContentAlignment { get; set; } = HorizontalAlignment.Left; 

    public double Width { get; set; } = 100; 

    public string ConditionExpression { get; set; } 

    public FilterType Type { get; set; } 

    private Condition m_conditionOperator; 
    public Condition SelectedCondition 
    { 
     get 
     { 
      return m_conditionOperator; 
     } 
     set 
     { 
      m_conditionOperator = value; 
     } 
    } 

    public IEnumerable<ConditionOperator> ChoosableConditions 
    { 
     get 
     { 
      return m_choosableConditions; 
     } 
     set 
     { 
      var mappings = new Dictionary<ConditionOperator, string>() 
      { 
       [ConditionOperator.Contains] = "Contains", 
       [ConditionOperator.EndsWith] = "Ends with", 
       [ConditionOperator.Equals] = "Equals", 
       [ConditionOperator.Greater] = "Greater", 
       [ConditionOperator.GreaterOrEqual] = "Greater or equal", 
       [ConditionOperator.Less] = "Less", 
       [ConditionOperator.LessOrEqual] = "Less or equal", 
       [ConditionOperator.StartsWith] = "Starts with" 
      }; 
      m_choosableConditions = value; 
      if (value != null && value.Any()) 
      { 
       //Conditions = new Condition[value.Count()]; 
       //int i = 0; 
       foreach (var condition in value) 
       { 
        Conditions.Add(new Condition(condition, mappings[condition])); 
        //Conditions[i] = new Condition(condition, mappings[condition]); 
        //i++; 
       } 
      } 
     } 
    } 

    public List<Condition> Conditions { get; private set; } = new List<Condition>(); 

    public object Value 
    { 
     get 
     { 
      return m_value; 
     } 
     set 
     { 
      m_value = value; 
     } 
    } 

    private bool ShouldShowOperatorsComboBox 
    { 
     get 
     { 
      return ChoosableConditions != null && ChoosableConditions.Any(); 
     } 
    } 

    private int InputPosition 
    { 
     get 
     { 
      int i = 0; 
      foreach (var filterControl in Filter.FilterControls) 
      { 
       if (filterControl == this) 
        return i; 
       i++; 
      } 
      throw new Exception($"Input cannot be found for filter {Filter.Name} and control {Label}."); 
     } 
    } 

    public SearchDescriptorFilterControl() { } 

    private Grid GetGrid() 
    { 
     var grid = new Grid(); 

     grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Auto }); 
     if (ShouldShowOperatorsComboBox) 
      grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Auto }); 
     grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Auto }); 

     return grid; 
    } 

    private Label GetLabel() 
    { 
     var label = new Label(); 

     label.Content = Label; 
     if (LabelWidth.HasValue) 
      label.Width = LabelWidth.Value; 
     else 
     { 
      var margin = label.Margin; 
      margin.Right += 5; 
      label.Margin = margin; 
     } 
     label.HorizontalContentAlignment = LabelContentAlignment; 
     Grid.SetColumn(label, 0); 

     return label; 
    } 

    private ComboBox GetConditionsComboBox() 
    { 
     var comboBox = new ComboBox(); 

     comboBox.Height = 21; 
     comboBox.Width = 75; 
     var margin = comboBox.Margin; 
     margin.Right += 5; 
     comboBox.Margin = margin; 
     comboBox.SetBinding(ItemsControl.ItemsSourceProperty, new Binding($"SearchDescriptor.SelectedFilter.FilterControls[{InputPosition}].Conditions")); 
     comboBox.IsSynchronizedWithCurrentItem = true; 
     comboBox.SelectedValuePath = nameof(Condition.ConditionOperator); 
     comboBox.DisplayMemberPath = nameof(Condition.Text); 
     comboBox.SetBinding(Selector.SelectedItemProperty, new Binding($"SearchDescriptor.SelectedFilter.FilterControls[{InputPosition}].SelectedCondition") 
     { 
      Mode = BindingMode.TwoWay, 
      UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged 
     }); 
     Grid.SetColumn(comboBox, 1); 

     return comboBox; 
    } 

    private TextBox GetTextInput() 
    { 
     var input = new TextBox(); 

     input.SetBinding(TextBox.TextProperty, new Binding($"SearchDescriptor.SelectedFilter.FilterControls[{InputPosition}].Value") { Delay = 1000, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged }); 

     return input; 
    } 

    private DatePicker GetDateInput() 
    { 
     var input = new DatePicker(); 

     input.SetBinding(DatePicker.SelectedDateProperty, new Binding($"SearchDescriptor.SelectedFilter.FilterControls[{InputPosition}].Value") { Delay = 1000, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged }); 

     return input; 
    } 

    public Grid GetInputFilter() 
    { 
     var grid = GetGrid(); 
     grid.Children.Add(GetLabel()); 

     //At the moment the column for filter input is 1 - immediately after the label. 
     var inputColumn = 1; 

     // If the collection has any element that means we must supply 
     // condition combo box so the user can choose a condition operator. 
     // For that we create another column. 
     if (ShouldShowOperatorsComboBox) 
     { 
      var comboBox = GetConditionsComboBox(); 
      grid.Children.Add(comboBox); 

      //Combo box comes after the label which means 
      //input filter comes after the combo box so we 
      //will increment the inputColumn value by 1. 
      inputColumn++; 
     } 

     //Filter input. 
     FrameworkElement inputFilter; 
     if (Type == FilterType.Date) 
      inputFilter = GetDateInput(); 
     else 
      inputFilter = GetTextInput(); 
     inputFilter.Width = Width; 

     Grid.SetColumn(inputFilter, inputColumn); 
     grid.Children.Add(inputFilter); 

     return grid; 
    } 
} 
+0

あなたは、バインディングモード双方向に設定しましたか?バインドされたすべてのオブジェクトがPropertyChangedEventを起動していることを確認しましたか? – pix

+0

Mode = TwoWayは必要ありません。私は他の方向に進んでいないからです。私は自分のモデルを更新しているビューに興味があります。その逆ではありません。 – Rob

+0

@ mm8これは私の質問の一番下にあります。単にstructをclassに置き換えてください。 – Rob

答えて

1

を実装するクラスSelectedItemプロパティにバインドするときは、SelectedValuePathは必要ありません。また、それはあなたがソースプロパティが定義されている同じクラスにComboBoxを作成するようだから、あなたにもこのようなバインディングのSourceを指定できます:

private ComboBox GetConditionsComboBox() 
{ 
    var comboBox = new ComboBox(); 

    comboBox.Height = 21; 
    comboBox.Width = 75; 
    var margin = comboBox.Margin; 
    margin.Right += 5; 
    comboBox.Margin = margin; 
    comboBox.SetBinding(ItemsControl.ItemsSourceProperty, new Binding("Conditions") { Source = this }); 
    comboBox.IsSynchronizedWithCurrentItem = true; 
    comboBox.DisplayMemberPath = nameof(Condition.Text); 
    comboBox.SetBinding(Selector.SelectedItemProperty, new Binding("SelectedCondition") 
    { 
     Source = this, 
     Mode = BindingMode.TwoWay, 
     UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged 
    }); 
    Grid.SetColumn(comboBox, 1); 

    return comboBox; 
} 
+0

ありがとうございます!これをバインドしてソースを設定すると、そのトリックが行われたようです。 – Rob

関連する問題