実行時にビューに追加されるコンボボックスコントロールを動的に作成しています。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;
}
}
あなたは、バインディングモード双方向に設定しましたか?バインドされたすべてのオブジェクトがPropertyChangedEventを起動していることを確認しましたか? – pix
Mode = TwoWayは必要ありません。私は他の方向に進んでいないからです。私は自分のモデルを更新しているビューに興味があります。その逆ではありません。 – Rob
@ mm8これは私の質問の一番下にあります。単にstructをclassに置き換えてください。 – Rob