我有一个非常普通的ViewModel,我想把一组值绑定到一个组合框。问题是没有任何约束力。我检查了ViewModel构造函数,并且正在加载数据,所以我怀疑它在我的XAML中,但我不知道在哪里。
public class OwnerOccupierAccountViewModel : ViewModelBase
{
readonly UserAccountContext _userAccountContext;
readonly LoadOperation<Structure> _loadStructures;
#region Properties
private ObservableCollection<Structure> _structures;
public ObservableCollection<Structure> Structures
{
get { return _structures; }
set
{
_structures = value;
RaisePropertyChanged("Structures");
}
}
private Structure _selectedStructure;
public Structure SelectedStructure
{
get { return _selectedStructure; }
set
{
_selectedStructure = value;
RaisePropertyChanged("SelectedStructure");
}
}
#endregion
public OwnerOccupierAccountViewModel()
{
_userAccountContext = new UserAccountContext();
if (!DesignerProperties.IsInDesignTool)
{
_loadStructures = _userAccountContext.Load(_userAccountContext.GetStructuresQuery());
_loadStructures.Completed += new EventHandler(_loadStructures_Completed);
}
}
void _loadStructures_Completed(object sender, EventArgs e)
{
_structures = new ObservableCollection<Structure>();
foreach (var structure in _loadStructures.Entities)
{
Structures.Add(structure);
}
}
}
<UserControl.Resources>
<viewmodel:OwnerOccupierAccountViewModel x:Key='ViewModel'></viewmodel:OwnerOccupierAccountViewModel>
</UserControl.Resources>
<ComboBox x:Name='cboApartments'
ItemsSource='{Binding Structures,Source={StaticResource ViewModel},Mode=TwoWay}'
Width='200' />
答案 0 :(得分:2)
尝试初始化您的ObservableCollection of Structures:
void _loadStructures_Completed(object sender, EventArgs e)
{
Structures = new ObservableCollection<Structure>(_loadStructures.Entities);
}
正如之前提到的,我认为你应该在这里改变秩序:
if (!DesignerProperties.IsInDesignTool)
{
//other code before
//_loadStructures = ...
_loadStructures.Completed += new EventHandler(_loadStructures_Completed);
//and now start loading
}
我做了类似的,非常简单的应用程序,以检查可能出错的地方,但一切正常。我将向您展示我的代码,以便您可以进行比较,也许您会在解决方案中找到一些错误。
Structure.cs
public class Structure
{
public Structure(string name)
{
Name = name;
}
public string Name { get; set; }
}
StructureService.cs
public class StructureService
{
public void GetAllStructures(Action<IList<Structure>> CompleteCallback)
{
var temp = new List<Structure>()
{
new Structure("Str1"),
new Structure("Str2"),
new Structure("Str3"),
new Structure("Str4"),
new Structure("Str5"),
new Structure("Str6"),
new Structure("Str7")
};
CompleteCallback(temp);
}
}
ViewModelBase.cs
public class ViewModelBase : INotifyPropertyChanged
{
protected void RaisePropertyChanged(string prop)
{
var temp = PropertyChanged;
if (temp != null)
{
temp(this, new PropertyChangedEventArgs(prop));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
OwnerOccupierAccountViewModel:
public class OwnerOccupierAccountViewModel : ViewModelBase
{
StructureService service;
public OwnerOccupierAccountViewModel()
{
if (!DesignerProperties.IsInDesignTool)
{
service = new StructureService();
service.GetAllStructures((result) =>
{
Structures = new ObservableCollection<Structure>(result);
});
}
}
private ObservableCollection<Structure> _structures;
public ObservableCollection<Structure> Structures
{
get { return _structures; }
set
{
_structures = value;
RaisePropertyChanged("Stuctures");
}
}
private Structure _selectedStructure;
public Structure SelectedStructure
{
get { return _selectedStructure; }
set
{
_selectedStructure = value;
RaisePropertyChanged("SelectedStructure");
}
}
}
MainPage.xaml中:
<UserControl x:Class="SilverlightApplication1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:SilverlightApplication1"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<UserControl.Resources>
<vm:OwnerOccupierAccountViewModel x:Key="ViewModel"/>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<ComboBox x:Name="cboApartments"
ItemsSource='{Binding Structures,Source={StaticResource ViewModel},Mode=TwoWay}'
SelectedItem="{Binding SelectedStructure, Source={StaticResource ViewModel},Mode=TwoWay}"
Width="100" Height="30">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</Grid>
</UserControl>
如果我在你的鞋子里,我会将xaml改为这样的观点:
SuggestedView:
<UserControl x:Class="SilverlightApplication1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:SilverlightApplication1"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<UserControl.DataContext>
<vm:OwnerOccupierAccountViewModel/>
</UserControl.DataContext>
<Grid x:Name="LayoutRoot" Background="White">
<ComboBox x:Name="cboApartments"
ItemsSource='{Binding Structures, Mode=TwoWay}'
SelectedItem="{Binding SelectedStructure, Mode=TwoWay}"
Width="100" Height="30">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</Grid>
</UserControl>
但我明白在你的场景中某种程度上是不可能的?
答案 1 :(得分:1)
尝试替换此行:
_structures = new ObservableCollection<Structure>();
用这个:
Structures = new ObservableCollection<Structure>();
并将ComboBox的绑定设置为OneWay。
编辑更新解决方案:
同时设置ComboBox的DisplayMemberPath属性:
DisplayMemberPath="StructureName"
答案 2 :(得分:1)
只有在更改属性时才会触发绑定。设置后备变量的行不会调用RaisePropertyChanged事件。即使它确实如此,此时它仍然是空的,你最终会得到一个空列表。
_structures = new ObservableCollection<Structure>();
当您添加到集合中时,您没有更改属性值,而是调用getter,因此RaisePropertyChanged将不再触发。
Structures.Add(structure);
您需要构建一个本地集合,然后将其用作Structures属性的值。这应该会导致绑定被触发。
var structures = new ObservableCollection<Structure>();
foreach ...
Structures = structures;
答案 3 :(得分:0)
您是直接绑定到ViewModel键作为源,但它是否在任何地方设置为DataContext?