如何使用XAML绑定ListView ItemsSource而不是在Code后面。?

时间:2011-11-12 06:45:50

标签: wpf listview binding mvvm-light

我正在关注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,但它无法正常工作。

请纠正我错在哪里。

2 个答案:

答案 0 :(得分:0)

为了快速获得完整的示例,您可以安装NUGet for Visual Studio并通过它在干净的WPF应用程序项目上安装MVVMLight包。然后它将设置一切,你会看到它是如何工作的。 虽然我将在这里描述基础知识。 MVVMLight支持开箱即用。 MVVMLigth的标准模板包括ViewModelLocatorMainViewModelViewModelLocator - 是包含所有其他视图模型的类。从一开始它只有一个属性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分配给源,它就可以正常工作。