如何使用不在代码后面的 XAML 绑定 ListView ItemsSource。?

Posted

技术标签:

【中文标题】如何使用不在代码后面的 XAML 绑定 ListView ItemsSource。?【英文标题】:How to Bind ListView ItemsSource using XAML not in Code behind.? 【发布时间】:2011-12-27 12:44:36 【问题描述】:

我正在关注 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 上。 Option 是属性的类,所以我使用的是 Menu.Option

My Menu 是 ContentMenuModel 类型的属性,ContentMenuModel 是包含 Option 和 Title 和 Image 属性的类。

查看 ViewModel 内的 Menu 属性

        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,但它不起作用。

请纠正我的错误。

【问题讨论】:

【参考方案1】:

为了快速获得完整示例,您可以安装 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 以声明方式设置的。

【讨论】:

嗨弗拉迪姆我有同样的你解释我,但它没有给我想要的结果,因为我更早之前有 RadCarousel Control,它运行良好,但列表视图不起作用。 显示您的 Option 类和 Menu 类,它们的外观。 我正在修改我的代码,请查看并纠正我。谢谢。【参考方案2】:

只需添加 ListView 的 Grid 并将 DataContext 分配给源,它就会工作。

【讨论】:

以上是关于如何使用不在代码后面的 XAML 绑定 ListView ItemsSource。?的主要内容,如果未能解决你的问题,请参考以下文章

如何在C#后面的代码中动态创建数据模板并绑定树视图层次结构数据

XAML WebView绑定到不在Xamarin Forms中的字符串

如何将嵌入式图像与后面 C# 代码中的字符串指定的变量 ImageSource 绑定?

选择器 ItemSource 值未绑定在 XAML ListView 中

XAML:相同的模板,不同的绑定

如何在代码中设置绑定?