我遵循 MVVM 模式,我想使用 XAML 绑定(bind) ListView ItemsSource,甚至不绑定(bind) 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 上。 Option 是属性的类,所以我使用 Menu.Option
My Menu 是 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 绑定(bind)到我的主窗口的 DataContext 和 Path=ViewModel 的 MainMenu,因此 MainMain 是 ViewModel 的对象,我可以在其中将此属性绑定(bind)到 ListView 的 ItemsSource,但它不起作用。
不对的地方请指正。
最佳答案
为了快速获得完整示例,您可以安装 NUGet for Visual Studio 并通过它在干净的 WPF 应用程序项目上安装 MVVMLight 包。然后它将设置一切,您将看到它是如何工作的。
虽然我会在这里描述基础知识。
MVVMLight 开箱即用地支持这一点。 MVVMLigth 的标准模板包括 ViewModelLocator
和 MainViewModel
。 ViewModelLocator
- 是包含所有其他 View 模型的类。从一开始它只有一个属性 public MainViewModel Main {get;}
。 ViewModelLocator
在 App.xaml 中注册为资源
<Application>
<Application.Resources>
<vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />
</Application.Resources>
</Application>
然后,在任何页面上,如果您想访问 View 模型,您应该简单地引用 Locator 资源并获取适合您的页面的属性。以下是 MainWindow
及其 MainViewModel
的示例:
<Window DataContext="{Binding Source={StaticResource Locator}, Path=Main}">
<Grid>
<TextBlock Text="{Binding Text}"/>
</Grid>
</Window>
在上面的示例中,我将 public string Text {get;}
属性添加到 MainViewModel
并进行了引用。例如,不需要任何代码隐藏,一切都是通过 xaml 以声明方式设置的。
关于wpf - 如何使用不在代码隐藏中的 XAML 绑定(bind) ListView ItemsSource。?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8103033/