我正在关注MVVM模式,我想使用XAML绑定ListView ItemsSource,而不是偶数 this.Datacontext = ObservableCollection属性。
我的代码是这样的:
<ListView x:Name="MenuBarList"
Grid.Row="2"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ItemsSource="{Binding Path=Menu.Option}"
Width="{Binding MainMenuWidth}"
SelectedItem="{Binding Path=SelectedMainMenuOption, Mode=TwoWay}" >
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}" TextWrapping="Wrap" IsHitTestVisible="False" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
并且Menu是属性,它将位于ViewModel上。选项是属性的类,所以我使用Menu.Option
我的菜单是ContentMenuModel类型的属性,ContentMenuModel是包含Option,Title和Image属性的类。
查看ViewModel内部菜单的属性
public const string MenuPropertyName = "Menu";
private ContentMenuModel _Menu = null;
/// <summary>
/// Gets the Menu collection.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
public ContentMenuModel Menu
{
get
{
return _Menu;
}
set
{
if (_Menu == value)
return;
_Menu = value;
// Update bindings, no broadcast
RaisePropertyChanged(MenuPropertyName);
}
}
ContentMenuModel类看起来像这样:
public class ContentMenuModel
{
#region Title
/// <summary>
/// The <see cref="Title" /> property's name.
/// </summary>
public const string TitlePropertyName = "Title";
private string _Title = String.Empty;
/// <summary>
/// Gets the Title property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
[Required]
[StringLength(128, ErrorMessage = "The Title value cannot exceed 128 characters. ")]
public string Title
{
get
{
return _Title;
}
set
{
if (_Title == value)
{
return;
}
var oldValue = _Title;
_Title = value;
// Update bindings, no broadcast
RaisePropertyChanged(TitlePropertyName);
}
}
#endregion
#region Options
/// <summary>
/// The <see cref="Options" /> property's name.
/// </summary>
public const string OptionsPropertyName = "Options";
private ObservableCollection<ContentMenuOptionModel> _Options = null;
/// <summary>
/// Gets the Options property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
public ObservableCollection<ContentMenuOptionModel> Options
{
get
{
return _Options;
}
set
{
if (_Options == value)
{
return;
}
var oldValue = _Options;
_Options = value;
RaisePropertyChanged(OptionsPropertyName);
}
}
#endregion
#region ContextText
/// <summary>
/// The <see cref="Options" /> property's name.
/// </summary>
public const string ContextTextPropertyName = "ContextText";
private ContentPageItem _ContextText = null;
/// <summary>
/// Gets the ContextText property.
/// Changes to that property's value raise the PropertyChanged event.
/// </summary>
public ContentPageItem ContextText
{
get
{
return _ContextText;
}
set
{
if (_ContextText == value)
{
return;
}
_ContextText = value;
RaisePropertyChanged(OptionsPropertyName);
}
}
#endregion
}
我已将ViewModelLocator绑定到我的主窗口的DataContext和Path = ViewModel的MainMenu,因此MainMain是ViewModel的对象,我可以将此属性绑定到ListView的ItemsSource,但它无法正常工作。
请纠正我错在哪里。
答案 0 :(得分:0)
为了快速获得完整的示例,您可以安装NUGet for Visual Studio并通过它在干净的WPF应用程序项目上安装MVVMLight包。然后它将设置一切,你会看到它是如何工作的。
虽然我将在这里描述基础知识。
MVVMLight支持开箱即用。 MVVMLigth的标准模板包括ViewModelLocator
和MainViewModel
。 ViewModelLocator
- 是包含所有其他视图模型的类。从一开始它只有一个属性public MainViewModel Main {get;}
。 ViewModelLocator
已在App.xaml
<Application>
<Application.Resources>
<vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />
</Application.Resources>
</Application>
然后,在任何页面上,如果要进入视图模型,只需引用Locator资源并获取适合您页面的属性。以下是MainWindow
及其MainViewModel
的示例:
<Window DataContext="{Binding Source={StaticResource Locator}, Path=Main}">
<Grid>
<TextBlock Text="{Binding Text}"/>
</Grid>
</Window>
在上面的示例中,我已将public string Text {get;}
属性添加到MainViewModel
并引用。在示例中,不需要任何代码隐藏,每个都是通过xaml以声明方式设置。
答案 1 :(得分:0)
只需添加ListView的Grid,并将DataContext分配给源,它就可以正常工作。