私はバックグラウンドにViewModel
(implemented INotifyPropertyChanged
)があり、クラスCategory
にはタイプstring
のプロパティが1つしかありません。私のComboBox SelectedItemは、カテゴリのインスタンスにバインドされています。インスタンスの値を変更しても、SelectedItemは更新されず、Comboboxは変更されません。
編集:コード
コンボボックス:
<ComboBox x:Name="categoryComboBox" Grid.Column="1" Grid.Row="3" Grid.ColumnSpan="2"
Margin="10" ItemsSource="{Binding Categories}"
DisplayMemberPath="Name" SelectedValue="{Binding NodeCategory, Mode=TwoWay}"/>
プロパティ:
private Category _NodeCategory;
public Category NodeCategory
{
get
{
return _NodeCategory;
}
set
{
_NodeCategory = value;
OnPropertyChanged("NodeCategory");
}
}
[Serializable]
public class Category : INotifyPropertyChanged
{
private string _Name;
[XmlAttribute("Name")]
public string Name
{
get
{
return _Name;
}
set
{
_Name = value;
OnPropertyChanged("Name");
}
}
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
[field:NonSerialized]
public event PropertyChangedEventHandler PropertyChanged;
}
そして私が試していることは:私が設定したとき
NodeCategory = some_list_of_other_objects.Category;
Combobox
で適切なDisplayMemberPath
を使用してそのアイテムを選択するには
この行で設定しているカテゴリ-
NodeCategory = some_list_of_other_objects.Category;
そして、あなたのカテゴリーコレクション(ItemsSource="{Binding Categories}"
)は同じオブジェクトを参照している必要があります。そうでない場合、SelectedItem
は機能しません。
次のようにSelectedValuePath
を使用することもできます-
<ComboBox x:Name="categoryComboBox"
ItemsSource="{Binding Categories}"
DisplayMemberPath="Name"
SelectedValuePath="Name"
SelectedValue="{Binding NodeCategory, Mode=TwoWay}" />
そしてコードであなたはこのようなことをすることができます-
private string _NodeCategory;
public string NodeCategory
{
get
{
return _NodeCategory;
}
set
{
_NodeCategory = value;
OnPropertyChanged("NodeCategory");
}
}
このように選択したアイテムを設定します-
NodeCategory = some_list_of_other_objects.Category.Name;
このように選択した値を使用します-
Category selectedCategory =
some_list_of_other_objects.FirstOrDefault(cat=> cat.Name == NodeCategory);
または
Category selectedCategory =
Categories.FirstOrDefault(cat=> cat.Name == NodeCategory);
別の可能な解決策は-
NodeCategory =
Categories.FirstOrDefault(cat=> cat.Name == some_list_of_other_objects.Category.Name);
このように、NodeCategory
プロパティはCategories
コレクション内のオブジェクトの参照を持ち、SelectedItem
は機能します。
XAMLにはいくつかの変更が必要ですが、実際の問題は、投稿したコードにあると私は思います。まず、コンボボックスItemSource
はCategoriesというプロパティにバインドされていますが、このプロパティのコーディング方法やNodeCategory
プロパティがアイテムと最初に同期される方法は示していません。
次のコードを使用してみてください。ユーザーがコンボボックスの値を変更しても、選択されたアイテムが同期されていることがわかります。
[〜#〜] xaml [〜#〜]
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<ComboBox x:Name="categoryComboBox"
Grid.Column="1"
Grid.Row="3"
Grid.ColumnSpan="2"
Margin="10"
ItemsSource="{Binding Categories}"
DisplayMemberPath="Name"
SelectedItem="{Binding NodeCategory}" />
<Label Content="{Binding NodeCategory.Name}" />
</StackPanel>
分離コード
public partial class MainWindow : Window, INotifyPropertyChanged
{
private ObservableCollection<Category> _categories = new ObservableCollection<Category>
{
new Category { Name = "Squares"},
new Category { Name = "Triangles"},
new Category { Name = "Circles"},
};
public MainWindow()
{
InitializeComponent();
NodeCategory = _categories.First();
this.DataContext = this;
}
public IEnumerable<Category> Categories
{
get { return _categories; }
}
private Category _NodeCategory;
public Category NodeCategory
{
get
{
return _NodeCategory;
}
set
{
_NodeCategory = value;
OnPropertyChanged("NodeCategory");
}
}
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
[Serializable]
public class Category : INotifyPropertyChanged
{
private string _Name;
[XmlAttribute("Name")]
public string Name
{
get
{
return _Name;
}
set
{
_Name = value;
OnPropertyChanged("Name");
}
}
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
[field: NonSerialized]
public event PropertyChangedEventHandler PropertyChanged;
}
私の小さな例から:
注:これは文字列(または別のリストのカテゴリ)を設定するだけですが、基本はここで同じにする必要があります。
基本的にこれは行われます:
private void button1_Click(object sender, RoutedEventArgs e)
{
(this.DataContext as ComboBoxSampleViewModel).SelectCategory("Categorie 4");
}
ここに私のXAMLがあります:
<Grid>
<ComboBox Height="23" HorizontalAlignment="Left" Margin="76,59,0,0"
Name="comboBox1" VerticalAlignment="Top" Width="120"
ItemsSource="{Binding List.Categories}"
DisplayMemberPath="Name"
SelectedValue="{Binding NodeCategory, Mode=TwoWay}" />
<Button Content="Button" Height="27" HorizontalAlignment="Left"
Margin="76,110,0,0" Name="button1" VerticalAlignment="Top"
Width="120" Click="button1_Click" />
</Grid>
ウィンドウのViewModel
class ComboBoxSampleViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
public CategoryList List { get; set; }
public ComboBoxSampleViewModel()
{
this.List = new CategoryList();
NodeCategory = List.Selected;
}
private ComboBoxSampleItemViewModel nodeCategory;
public ComboBoxSampleItemViewModel NodeCategory
{
get
{
return nodeCategory;
}
set
{
nodeCategory = value;
NotifyPropertyChanged("NodeCategory");
}
}
internal void SelectCategory(string p)
{
this.List.SelectByName(p);
this.NodeCategory = this.List.Selected;
}
}
この小さなクラスの助けを借りて:
public class CategoryList
{
public ObservableCollection<ComboBoxSampleItemViewModel> Categories { get; set; }
public ComboBoxSampleItemViewModel Selected { get; set; }
public CategoryList()
{
Categories = new ObservableCollection<ComboBoxSampleItemViewModel>();
var cat1 = new ComboBoxSampleItemViewModel() { Name = "Categorie 1" };
var cat2 = new ComboBoxSampleItemViewModel() { Name = "Categorie 2" };
var cat3 = new ComboBoxSampleItemViewModel() { Name = "Categorie 3" };
var cat4 = new ComboBoxSampleItemViewModel() { Name = "Categorie 4" };
Categories.Add(cat1);
Categories.Add(cat2);
Categories.Add(cat3);
Categories.Add(cat4);
this.Selected = cat3;
}
internal void SelectByName(string p)
{
this.Selected = this.Categories.Where(s => s.Name.Equals(p)).FirstOrDefault();
}
}
そして、このアイテムViewModel
public class ComboBoxSampleItemViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
private string name;
public string Name
{
get
{
return name;
}
set
{
name = value;
NotifyPropertyChanged("Name");
}
}
}
Comboboxがビューモデルのオブジェクトクラスにバインドされているが、送信者オブジェクトのSelectionBoxItem
(コードビハインドのSelectionChanged
内)がその型を持たない場合、それはまだロードされていることを意味します。
ComboBox combo = sender as ComboBox;
if (combo.SelectionBoxItem.GetType() == typeof(BindedClass))
{
// Not loading
}