WPF ListView 选择无法在加载时清除?
我查看了几个相关的答案,并确定我可以通过设置 lstData.SelectedIndex = -1; 以编程方式清除选择。但是,当我在启动时设置数据上下文后立即执行此操作时,不知何故它永远不会工作并被设置为选择列表中的第一个元素。
我还尝试将设置添加到 XAML,-1 实际上是 Visual Studio 的默认值,尽管除非您设置它,否则它实际上并不在 XAML 中。即:
<ListView Margin="6,6,6,203"
IsSynchronizedWithCurrentItem="True"
x:Name="lstData"
ItemsSource="{Binding}"
SelectionChanged="lstData_SelectionChanged"
HorizontalContentAlignment="Right"
ItemContainerStyle="{StaticResource ItemContStyle}"
SelectedIndex="-1">
但这也没有效果。
另外,令人着迷的是,如果我输入 lstData.SelectedIndex = 3;在我的 LoadData 方法中,它将从选择的第三个成员开始设置。
这是我的相关窗口加载代码:
public Window1()
{
InitializeComponent();
// Set start and end dates to day after tomorrow, and
// the next day, by default:
StartDate = DateTime.Now.AddDays(1);
EndDate = StartDate.AddDays(2);
txtStartDate.Text = StartDate.ToShortDateString();
txtEndDate.Text = EndDate.ToShortDateString();
LoadData();
}
public void LoadData()
{
App.RefreshMembers();
App.CalculateNeededMeals(StartDate, EndDate);
// Bind the ListBox to our ObserveableCollection
LayoutRoot.DataContext =
App.db.PFW_Members.OrderBy("FullName",true).OrderBy("CancelDate",true);
lstData.SelectedIndex = -1;
}
在其他情况下会调用 LoadData(),在这种情况下它会清除选择。只是不是第一次加载窗口。好像有一些初始化线程尚未真正完成,如果启动时为 -1,则将选择设置为 0。
哦,是的,我确实有一个选择更改处理程序,但它不会更改选择,即:
private void lstData_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (lstData.SelectedItem == null)
{
btnReactivate.IsEnabled = false;
btnDeactivate.IsEnabled = false;
}
else
{
if (((PFW_Member)lstData.SelectedItem).CancelDate == null)
{
btnReactivate.IsEnabled = false;
btnDeactivate.IsEnabled = true;
}
else
{
btnReactivate.IsEnabled = true;
btnDeactivate.IsEnabled = false;
}
}
}
是否有某种方法可以让它真正等到加载,然后做一些事情,或者设置延迟事件或其他东西,或者做有人对这里可能发生的事情有知识或理论吗?
感谢您的任何提示!
I looked at several related answers, and determined that I can programmatically clear the selection by setting lstData.SelectedIndex = -1; However, when I do it right after setting the data context on startup, somehow it never works and gets set to select the first element in the list.
I also tried adding the setting to the XAML, and -1 is actually Visual Studio's default value, though it isn't actually in the XAML unless you set it. I.e.:
<ListView Margin="6,6,6,203"
IsSynchronizedWithCurrentItem="True"
x:Name="lstData"
ItemsSource="{Binding}"
SelectionChanged="lstData_SelectionChanged"
HorizontalContentAlignment="Right"
ItemContainerStyle="{StaticResource ItemContStyle}"
SelectedIndex="-1">
But this also has no effect.
Also, fascinatingly, if I put lstData.SelectedIndex = 3; in my LoadData method, it WILL start set with the third member selected.
This is my relevant window loading code:
public Window1()
{
InitializeComponent();
// Set start and end dates to day after tomorrow, and
// the next day, by default:
StartDate = DateTime.Now.AddDays(1);
EndDate = StartDate.AddDays(2);
txtStartDate.Text = StartDate.ToShortDateString();
txtEndDate.Text = EndDate.ToShortDateString();
LoadData();
}
public void LoadData()
{
App.RefreshMembers();
App.CalculateNeededMeals(StartDate, EndDate);
// Bind the ListBox to our ObserveableCollection
LayoutRoot.DataContext =
App.db.PFW_Members.OrderBy("FullName",true).OrderBy("CancelDate",true);
lstData.SelectedIndex = -1;
}
And LoadData() gets called in other circumstances, and in that case it DOES clear the selection. Just not the first time the window loads. As if, there is some initialization thread that is not really finished and goes and sets the selection to 0 if it is -1 on startup.
Oh and yes I do have a selection changed handler, but it doesn't change the selection, i.e.:
private void lstData_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (lstData.SelectedItem == null)
{
btnReactivate.IsEnabled = false;
btnDeactivate.IsEnabled = false;
}
else
{
if (((PFW_Member)lstData.SelectedItem).CancelDate == null)
{
btnReactivate.IsEnabled = false;
btnDeactivate.IsEnabled = true;
}
else
{
btnReactivate.IsEnabled = true;
btnDeactivate.IsEnabled = false;
}
}
}
Is there some way to make it really wait until loaded, and then do stuff, or to set a delayed event or something, or does someone have knowledge or a theory about what might be going on here?
Thanks for any tips!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
只需设置 IsSynchronizedWithCurrentItem="False"。这将是修复它的最简单方法。
这里发生的事情是这样的:在一切都初始化之后(即在构造函数之后),绑定将启动。此时将设置 ListBox 的 ItemsSource。在此步骤中,一些 ICollectionView 魔法会在幕后发生。本质上,ListBox 将连接到源集合的默认 CollectionView,其 CurrentItem 属性始终默认为第一项。现在,如果 IsSynchronizedWithCurrentItem 为 true,ListBox 会将 SelectedItem 更新为等于 ICollectionView.CurrentItem。这就是导致您提到的问题的原因。
(注意:在所有这些发生之后,Loaded 事件将被触发。因此,dnr3 在 Loaded 事件中设置 SelectedIndex=-1 的注释也应该有效)。
希望这是有道理的。
Just set IsSynchronizedWithCurrentItem="False". This will be the easiest way to fix it.
What's happening here is this: after everything gets Initialized (i.e. after the constructor), the Bindings will kick in. The ListBox's ItemsSource will be set at this time. During this step, some ICollectionView magic happens behind the scenes. Essentially, the ListBox will get connected to the source collection's default CollectionView, whose CurrentItem property always defaults to the first item. Now, if IsSynchronizedWithCurrentItem is true, the ListBox will update the SelectedItem to be equal to the ICollectionView.CurrentItem. This is what's causing the issue you mentioned.
(Note: after all of these happens, the Loaded event will get fired. So, dnr3's comment of setting the SelectedIndex=-1 in the Loaded event should also work).
Hope this makes sense.