将ListBox
绑定到CollectionViewSource
(用于视图过滤)时,重新绑定到Source
属性时,ListBox
会自动选择第一个项目(导致SelectedItem
绑定同时也开火了。
我不希望列表中的第一项自动选择,也不希望SelectedItem
的setter完全触发(因为我选择了一个项目时会调用其他逻辑)。 / p>
这是一个自包含的示例,将其放在一个空白的新WPF应用程序中以演示:
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
namespace TestBinding
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var template = new DataTemplate();
FrameworkElementFactory tbFactory = new FrameworkElementFactory(typeof(TextBlock));
tbFactory.SetBinding(TextBlock.TextProperty, new Binding("Name"));
template.VisualTree = tbFactory;
var itemsA = new List<Item>
{
new Item { Name = "A Item 1" },
new Item { Name = "A Item 2" },
new Item { Name = "A Item 3" },
new Item { Name = "A Item 4" },
new Item { Name = "A Item 5" },
new Item { Name = "A Item 6" },
};
var itemsB = new List<Item>
{
new Item { Name = "B Item 1" },
new Item { Name = "B Item 2" },
new Item { Name = "B Item 3" },
new Item { Name = "B Item 4" },
};
var itemsC = new List<Item>
{
new Item { Name = "C Item 1" },
new Item { Name = "C Item 2" },
new Item { Name = "C Item 3" },
new Item { Name = "C Item 4" },
new Item { Name = "C Item 5" },
new Item { Name = "C Item 6" },
new Item { Name = "C Item 7" },
new Item { Name = "C Item 8" },
};
var sp = new StackPanel();
var b1 = new Button
{
Content = "Bind A"
};
b1.Click += (_, __) =>
{
Items = itemsA;
};
var b2 = new Button
{
Content = "Bind B"
};
b2.Click += (_, __) =>
{
Items = itemsB;
};
var b3 = new Button
{
Content = "Bind C"
};
b3.Click += (_, __) =>
{
Items = itemsC;
};
var list = new ListBox
{
ItemTemplate = template
};
list.SetBinding(ItemsControl.ItemsSourceProperty, new Binding("ItemFilter.View")
{
Source = this
});
list.SetBinding(Selector.SelectedItemProperty, new Binding("SelectedItem")
{
Source = this
});
sp.Children.Add(b1);
sp.Children.Add(b2);
sp.Children.Add(b3);
sp.Children.Add(list);
(Content as Grid).Children.Add(sp);
ItemFilter = new CollectionViewSource();
DataContext = this;
}
private List<Item> _Items;
public List<Item> Items
{
get { return _Items; }
set
{
_Items = value;
ItemFilter.Source = _Items;
}
}
#region Dependency Properties
public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register("SelectedItem", typeof(Item), typeof(MainWindow), new PropertyMetadata(default(Item)));
public Item SelectedItem
{
get { return (Item)GetValue(SelectedItemProperty); }
set { SetValue(SelectedItemProperty, value); }
}
public static readonly DependencyProperty ItemFilterProperty = DependencyProperty.Register("ItemFilter", typeof(CollectionViewSource), typeof(MainWindow), new PropertyMetadata(default(CollectionViewSource)));
public CollectionViewSource ItemFilter
{
get { return (CollectionViewSource)GetValue(ItemFilterProperty); }
set { SetValue(ItemFilterProperty, value); }
}
#endregion
}
public class Item : INotifyPropertyChanged
{
private string _Name;
public string Name
{
get { return _Name; }
set { NotifyPropertyChanged(ref _Name, value, "Name"); }
}
#region INPC
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged<T>(ref T item, T value, string name)
{
item = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
#endregion
}
}
答案 0 :(得分:1)
简短回答:你不能......更新数据源会自动更新显示,并自动将选择恢复回列表中的第一个。你唯一能做的就是记住内存中的选择,然后在更新绑定后重新选择它,但既然你说这不是你的选择,那么这是不可能的。
除非您不介意设置标记以跳过您的Select事件代码...
例如:
记住,
更新装订
将标志设置为“跳过代码”
从记忆中选择项目
将标志设置为“运行代码”
答案 1 :(得分:-1)
尝试collectviewsource.view.moveto(-1)。