在WPF中的多个列表框上的TwoWay绑定到ListBox SelectedItem

时间:2010-03-16 00:45:16

标签: c# wpf data-binding listbox

我有一个场景,我有一个全局可用的属性窗口(类似于Visual Studio中的属性窗口),它绑定到我的模型的SelectedObject属性。我有许多不同的浏览和选择对象的方法,所以我的第一次尝试是将它们直接绑定到SelectedObject。例如:

<ListBox ItemsSource="{Binding ActiveProject.Controllers}" 
SelectedItem="{Binding SelectedObject, Mode=TwoWay}"/>

<ListBox ItemsSource="{Binding ActiveProject.Machines}" 
SelectedItem="{Binding SelectedObject, Mode=TwoWay}"/>

当每个列表中有多个项目时,这很有效,但如果列表只有一个项目,则会失败。当我选择项目时,SelectedObject不会更新,因为列表仍然认为其原始项目已被选中。我相信这是因为当SelectedObject不是列表中的对象时,双向绑定只是忽略源的更新,而是保持列表的SelectedItem不变。这样,绑定就会变得不同步。

当SelectedObject不在列表中时,是否有人知道确保列表框重置其SelectedItem的方法?有没有更好的方法来做这个没有遭受这个问题?

2 个答案:

答案 0 :(得分:3)

丹的回答帮助我解决了我的问题。看起来好像关键是绑定对象首先重新绑定为空值,然后再重新绑定到新值。

我的解决方案中没有Postsharp或者需要维护所选对象的列表,这是我需要的唯一代码。

    Public Property MyProperty() As Object
        Get
            Return Me._MyProperty
        End Get
        Set(value As Object)
            Me._MyProperty = Nothing

            NotifyOfPropertyChange(Function() MyProperty)

            Me._MyProperty = value

            NotifyOfPropertyChange(Function() MyProperty)
        End Set
    End Property

答案 1 :(得分:1)

好吧,我找到了解决这个问题的办法,但这让我有些不适。我将模型中的SelectedObject属性修改为:

public Object SelectedObject
{
    get
    {
        return _selectedObject;
    }
    set
    {
        if (value != _selectedObject)
        {
            //HACK
            //Pulse 'null' between changes to reset listening list controls
            if (value != null)
                SelectedObject = null;

            if (_selectedObject != null)
                SelectedObjects.Remove(_selectedObject);

            _selectedObject = value;
            if (value != null)
                SelectedObjects.Add(value);
        }
    }
}

这会强制所有数据绑定列表控件在我们更新为“真正的”SelectedObject之前将其SelectedItem重置为null。另外,PostSharp正在处理NotifyPropertyChanged的内容,以防你想知道为什么它丢失了。

如果可能的话,我更喜欢一种不那么狡猾的解决方案,但我确实喜欢这样一个事实:这样可以保持XAML中的绑定清晰(无需更改。)