【问题标题】:Databinding ListBox SelectedItems to ViewModel将 ListBox SelectedItems 数据绑定到 ViewModel
【发布时间】:2026-01-16 19:55:01
【问题描述】:

我正在尝试使用我创建的附加属性对 ListBox SelectedItems 属性进行数据绑定。我设置了一个名为 ListBoxFix 的类,它位于一个名为 ControlFixes 的文件夹中。它的代码是一个非常简单的依赖属性,如下所示:

using System.Windows;
using System.Windows.Controls;

namespace QMAC.ControlFixes
{
    public static class ListBoxFix
    {
        public static bool GetSelectedItemsBinding(ListBox element)
        {
            return (bool)element.GetValue(SelectedItemsBindingProperty);
        }

        public static void SetSelectedItemsBinding(ListBox element, bool value)
        {
            element.SetValue(SelectedItemsBindingProperty, value);
            if (value)
            {
                element.SelectionChanged += (sender, args) =>
                {
                    var x = element.SelectedItems;
                };
            }
        }

        public static readonly DependencyProperty SelectedItemsBindingProperty =
            DependencyProperty.RegisterAttached("FixSelectedItemsBinding",
            typeof(bool), typeof(FrameworkElement), new PropertyMetadata(false));
    }
}

在我的 XAML 代码中,我有以下标记:

<Window x:Class="QMAC.MainWindow"
        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:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
        xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras"
        xmlns:fix="clr-namespace:QMAC.ControlFixes"
        x:Name="Window"
        DataContext="{Binding Main, Mode=OneWay, Source={StaticResource Locator}}"
        Title="QMAC" Width="554.779" ResizeMode="CanMinimize" Height="539" Icon="logo.ico" >
    <Grid Background="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}" RenderTransformOrigin="0.593,0.948" Margin="0,0,0,1">

        <ListBox x:Name="schoolListBox" HorizontalAlignment="Left" Margin="25,86,0,0" Width="274" FontSize="16" SelectionMode="Extended" ItemsSource="{Binding LocationList}" fix:ListBox.SelectedItemsBindingProperty="true"  VerticalAlignment="Top" Height="364"></ListBox>
    </Grid>
</Window>

不幸的是,我在设置标记时遇到了 3 个错误。他们是

Error   1   The name "ListBox" does not exist in the namespace "clr-namespace:QMAC.ControlFixes".
Error   2   The attachable property 'SelectedItemsBindingProperty' was not found in type 'ListBox'.
Error   3   The property 'ListBox.SelectedItemsBindingProperty' does not exist in XML namespace 'clr-namespace:QMAC.ControlFixes'.

我主要是想了解它为什么要在我的 ControlFixes 命名空间中寻找 ListBox?

【问题讨论】:

    标签: c# wpf xaml data-binding listbox


    【解决方案1】:

    您以错误的方式声明和使用附加属性。我建议你仔细阅读this well written overview

    你的代码有以下错误:

    • 您的附加属性的所有者类型被错误地指定为FrameworkElement
    • 注册的属性名称与包含它的静态字段不匹配
    • 您尝试通过 ListBox 类使用附加属性,尽管您已在 ListBoxFix 类中定义了它。

    正确的附加属性定义应如下所示:

    public static class ListBoxFix
    {
        public static bool GetSelectedItemsBinding(ListBox element)
        {
            return (bool)element.GetValue(SelectedItemsBindingProperty);
        }
    
        public static void SetSelectedItemsBinding(ListBox element, bool value)
        {
            element.SetValue(SelectedItemsBindingProperty, value);
        }
    
        public static readonly DependencyProperty SelectedItemsBindingProperty =
            DependencyProperty.RegisterAttached("SelectedItemsBinding",
            typeof(bool), typeof(ListBoxFix), new PropertyMetadata(false));
    }
    

    请注意,RegisterAttached() 方法的 ownerType 参数提供了包含附加属性的类的类型。也看看 name 参数。

    附加属性的正确用法:

    <ListBox fix:ListBoxFix.SelectedItemsBinding="true"/>
    

    更新:

    您可能希望以“WPF”样式使用您的附加属性。那么最好将您的类设计为从DependencyObject 派生。这是 MSDN 所说的:

    如果您的类严格定义附加属性以用于其他类型,则该类不必从 DependencyObject 派生。但是,如果您遵循将附加属性也作为依赖属性的整体 WPF 模型,则确实需要从 DependencyObject 派生。

    【讨论】:

    • 我的修复指向了我的正确命名空间,但它仍然告诉我在该命名空间中找不到 ListBoxFix。
    • @RandomlyKnighted,有时可能是由 IntelliSence 引起的。尝试清理并重建您的项目,或关闭 Visual Studio 并再次重新启动它。我已经在 VS 中检查了我的代码,它可以工作。
    • 为了明确您的更新,因为我的 ListBoxFix 类仅用于添加依赖属性,所以我的类需要从 DependencyObject 继承属性?
    • @RandomlyKnighted,一个简单的答案是:不,不必。
    • 如果我想将此值作为多重绑定的一部分传递给按钮,是&lt;Binding ElementName="schoolListBox" Path="SelectedItemsBinding" /&gt; 还是我必须做其他事情?