见下面的代码
Visual Studio 2010
ListBox上方有一个TextBox
通过绑定,选择项目时,TextBox可以变大或变小
这导致ListBox移动
当ListBox移动时,所选项目不是被点击的项目
所选项目是移动的ListBox上鼠标下的项目
有时甚至根本不会选择(尝试从9到10或从10到9)
在此代码中,重现问题甚至奇数产生不同的长度
所以,如果你从奇数到奇数甚至是偶数,那么没有问题
如果你从顶部的奇数到底部(不滚动),那么有时会选择一个甚至不在视野中的项目。
在实际代码中,TextBox是项目的描述,描述的长度不同
有趣的是调试,get {return boundText;有一个断点。然后它确实选择了合适的项目
我认为它处理选择,然后测量UI,然后在新UI上第二次处理选择
由于它在调试中表现不同,因此很难弄清楚。
<Window x:Class="ListBoxMissClick.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Row="0" Grid.Column="0" Text="{Binding Path=BoundText}" TextWrapping="Wrap" />
<ListBox Grid.Row="1" Grid.Column="0" ItemsSource="{Binding Path=BoundList}" SelectedItem="{Binding Path=BoundListSelected, Mode=TwoWay}"/>
</Grid>
</Window>
using System.ComponentModel;
namespace ListBoxMissClick
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
private string boundListSelected;
private string boundText = string.Empty;
private List<string> boundList = new List<string>();
private bool shortLong = true;
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
public MainWindow()
{
for (int i = 0; i < 1000; i++)
{
boundList.Add(i.ToString());
}
InitializeComponent();
}
public string BoundText
{
get { return boundText; }
set
{
if (boundText != value)
{
boundText = value;
NotifyPropertyChanged("BoundText");
}
}
}
public List<string> BoundList { get { return boundList; } }
public string BoundListSelected
{
get { return boundListSelected; }
set
{
boundListSelected = value;
if (Int32.Parse(value) % 2 == 0)
{
BoundText = value.ToString() + " something very long something very long something very long something very long something very long something very long something very long something very long something very long something very longsomething very long something very long something very long something very long something very longsomething very long something very long something very long something very long something very longsomething very long something very long something very long something very long something very longsomething very long something very long something very long something very long something very long";
}
else
{
BoundText = value.ToString() + " something short ";
}
}
}
private void ListBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
BoundText = " something very long something very long something very long something very long something very long something very long something very long something very long something very long something very longsomething very long something very long something very long something very long something very longsomething very long something very long something very long something very long something very longsomething very long something very long something very long something very long something very longsomething very long something very long something very long something very long something very long";
}
}
}
除了接受的答案Mouse.Capture和ReleaseMouseCapture工作。
set
{
Mouse.Capture(this);
{
boundListSelected = value;
if (Int32.Parse(value) % 2 == 0)
{
BoundText = value.ToString() + " something very long something very long something very long something very long something very long something very long something very long something very long something very long something very longsomething very long something very long something very long something very long something very longsomething very long something very long something very long something very long something very longsomething very long something very long something very long something very long something very longsomething very long something very long something very long something very long something very long";
}
else
{
BoundText = value.ToString() + " something short ";
}
}
ReleaseMouseCapture();
}
答案 0 :(得分:4)
我稍微重写了你的代码。诀窍是使用MouseCapture来避免多个事件处理(使用原始代码,由于在按下鼠标按钮时布局改变,listBox最多只能进行三次选择)
以下是代码:
<强> MainWindow.xaml 强>
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="TextEditor.MainWindow"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox Grid.Row="0" Text="{Binding Path=BoundText}" TextWrapping="Wrap" />
<ListBox Grid.Row="1"
ItemsSource="{Binding Path=BoundList}"
SelectedItem="{Binding Path=BoundListSelected, Mode=TwoWay}"/>
</Grid>
</Window>
<强> MainWindow.xaml.cs 强>
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Input;
namespace TextEditor
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public string BoundText
{
get { return (string)GetValue(BoundTextProperty); }
set { SetValue(BoundTextProperty, value); }
}
// Using a DependencyProperty as the backing store for BoundText. This enables animation, styling, binding, etc...
public static readonly DependencyProperty BoundTextProperty =
DependencyProperty.Register("BoundText", typeof(string), typeof(MainWindow), new PropertyMetadata(string.Empty));
public string BoundListSelected
{
get { return (string)GetValue(BoundListSelectedProperty); }
set { SetValue(BoundListSelectedProperty, value); }
}
// Using a DependencyProperty as the backing store for BoundListSelected. This enables animation, styling, binding, etc...
public static readonly DependencyProperty BoundListSelectedProperty =
DependencyProperty.Register("BoundListSelected", typeof(string), typeof(MainWindow), new PropertyMetadata(string.Empty, OnBoundListSelectedChanged));
private static void OnBoundListSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var mainWindow = d as MainWindow;
var value = e.NewValue as string;
Mouse.Capture(mainWindow);
if (Int32.Parse(value) % 2 == 0)
{
mainWindow.BoundText = value.ToString() + " something very long something very long something very long something very long something very long something very long something very long something very long something very long something very longsomething very long something very long something very long something very long something very longsomething very long something very long something very long something very long something very longsomething very long something very long something very long something very long something very longsomething very long something very long something very long something very long something very long";
}
else
{
mainWindow.BoundText = value.ToString() + " something short ";
}
mainWindow.ReleaseMouseCapture();
}
public MainWindow()
{
for (int i = 0; i < 1000; i++)
{
boundList.Add(i.ToString());
}
InitializeComponent();
DataContext = this;
}
public List<string> BoundList { get { return boundList; } }
private List<string> boundList = new List<string>();
}
}
编辑:我实际上改变了MainWindow的编码方式(没有必要在DependencyObject上实现INotifyPropertyChanged,所以我只是删除了它并设置了两个依赖属性)但你可以尝试解决你的问题你的ogirinal代码只需在设置BoundText之前捕获鼠标,然后释放它。
答案 1 :(得分:1)
您可以在Thread.Sleep
setter中添加BoundListSelected
来解决您的问题,但我认为更好的解决方案是在这种情况下使用网格列。使用列时,您无需使用Thread.Sleep
。
public string BoundListSelected
{
get { return boundListSelected; }
set
{
Thread.Sleep(TimeSpan.FromSeconds(.2));
boundListSelected = value;
if (Int32.Parse(value) % 2 == 0)
{
BoundText = value.ToString() + " something very long something very long something very long something very long something very long something very long something very long something very long something very long something very longsomething very long something very long something very long something very long something very longsomething very long something very long something very long something very long something very longsomething very long something very long something very long something very long something very longsomething very long something very long something very long something very long something very long";
}
else
{
BoundText = value.ToString() + " something short ";
}
}
}
如果您不想使用Thread.Sleep
,可以使用网格列:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" Text="{Binding Path=BoundText}" TextWrapping="Wrap" />
<ListBox Grid.Column="1" ItemsSource="{Binding Path=BoundList}" SelectedItem="{Binding Path=BoundListSelected, Mode=TwoWay}"/>
</Grid>