我有ListView
,显示了许多元素。根据元素的类型,选择正确的DataTemplate
来显示它们。其中一个模板用于项目列表,这些项目在ComboBox
内呈现。
的DataTemplate
<DataTemplate x:Key="comboBoxTemplate0">
<ComboBox
ItemsSource="{Binding options}" ToolTip="{Binding Title}"
Margin="2" MinWidth="50" MinHeight="20" HorizontalAlignment="Stretch"
VerticalAlignment="Center">
<ComboBox.ItemContainerStyle>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="VerticalContentAlignment" Value="Top" />
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
</DataTemplate>
现在,我发现了一个我无法解释的问题,我相信它可能与某种方式有关,但我不知道。当我打开ComboBox的下拉列表时,我无法拖动内部ScrollViewer。我可以使用滚轮上下移动,或箭头键,但拖动不起作用,而ListView中的ScrollViewer被激活(因此拖动内部ScrollViewer移动外部)。
我似乎无法重现这个错误,也找不到任何让它发生在他们身上的人,所以我不知所措。我正在考虑放弃并简单地隐藏内部ScrollViewer,以便它不会被拖动。
这种行为可能是什么原因?当我尝试拖动内部ComboBox的ScrollViewer时,为什么外部ListView的ScrollViewer会移动?
修改
事情尝试了:将CanContentScroll
设置为false - 不起作用
PreviewDragOver
ListView正在侦听4个事件:
的PreviewMouseLeftButtonDown
private void List_PreviewMouseLeftButtonDown (object Sender, MouseEventArgs E)
{
startPoint_ = E.GetPosition (null);
}
的MouseMove
private void List_MouseMove (object Sender, MouseEventArgs E)
{
if (allowDrag_)
{
Vector Difference = startPoint_ - E.GetPosition (null);
if (Mouse.LeftButton == MouseButtonState.Pressed &&
(Math.Abs (Difference.X) > SystemParameters.MinimumHorizontalDragDistance ||
Math.Abs (Difference.Y) > SystemParameters.MinimumVerticalDragDistance))
{
PerformDragAndDrop ((DependencyObject)E.OriginalSource, (ListView)Sender);
}
}
}
dragEnter事件
private void List_DragEnter (object Sender, DragEventArgs E)
{
if (!E.Data.GetDataPresent (Strings.DragnDropFormatString) ||
Sender == E.Source)
{
E.Effects = DragDropEffects.None;
}
}
并删除
private void List_Drop (object Sender, DragEventArgs E)
{
if (E.Data.GetDataPresent (Strings.DragnDropFormatString))
{
CSettingBase Data = E.Data.GetData (Strings.DragnDropFormatString) as CSettingBase;
if (LoadedSettings.FirstOrDefault (s => s.Name == Data.Name) == null)
{
LoadedSettings.Add (Data);
Utility.AutoSizeGridViewColumns (ListViewControl);
this.HideColumns (8);
if (((ObservableCollection<CSettingBase>)this.ListViewControl.ItemsSource).FirstOrDefault (x => x.IsGroup == true) == null)
{
this.ExpandColumns (1);
}
else
{
this.ExpandColumns (8);
}
}
}
}
PerformDragAndDrop
public void PerformDragAndDrop (DependencyObject Origin, ListView List)
{
ListViewItem GridRow = Utility.FindAncestor<ListViewItem> (Origin);
if (GridRow != null)
{
CSettingBase Data = (CSettingBase)List.ItemContainerGenerator.ItemFromContainer (GridRow);
// Initialize the Drag and Drop operation
DataObject DragData = new DataObject (Strings.DragnDropFormatString, Data);
DragDrop.DoDragDrop (GridRow, DragData, DragDropEffects.Move);
}
}
答案 0 :(得分:1)
在我看来,问题是您List_*event*
正在触发,而不是ComboBox
事件。
我认为这是有道理的 - 除非我错过了什么......:)
原因是,它们都是控件,但其中一个包含在另一个控件中。因此,举例来说,如果您的ListView
是全屏的,那么每次点击任何内容时,
private void List_PreviewMouseLeftButtonDown (object Sender, MouseEventArgs E)
{
startPoint_ = E.GetPosition (null);
}
仍在被触发。
同样, 每次 你的鼠标光标都会移动,你就会触发:
private void List_MouseMove (object Sender, MouseEventArgs E)
{
if (allowDrag_)
{
Vector Difference = startPoint_ - E.GetPosition (null);
if (Mouse.LeftButton == MouseButtonState.Pressed &&
(Math.Abs (Difference.X) > SystemParameters.MinimumHorizontalDragDistance ||
Math.Abs (Difference.Y) > SystemParameters.MinimumVerticalDragDistance))
{
PerformDragAndDrop ((DependencyObject)E.OriginalSource, (ListView)Sender);
}
}
}
您可以通过在调试时单步调试代码来检查这一点,或者在这些事件上设置断点,并在尝试操作从属控件时查看它们是否被触发。
最后,如果它们是,你可以简单地在你的代码中放一个子句来检查实际上有什么焦点,并确保它是listview。这样做的问题是,即使激活了子控件,它也可能保持焦点。采取相同行动的另一种方式是确保没有孩子有焦点。这将是更多的代码,因为您要检查包含的每个元素而不是包含的元素。但是,你可能只是使用一种方法来检查这一点。例如:
private void List_PreviewMouseLeftButtonDown (object Sender, MouseEventArgs E)
{
var fs = GetFocusScope(myComboBox);
IInputElement fe = FocusManager.GerFocusedElement(fs);
if (fe == myListView)
{
startPoint_ = E.GetPosition (null);
}
}
或强>
private bool focusCheck()
{
bool childFocused;
var fs = GetFocusScope(myComboBox);
IInputElement fe = FocusManager.GetFocusedElement(fs);
if (fe == myComboBox) { childFocused = true; }
if (fe == myButton) { childFocused = true; }
// then repeat the above for every control contained by your list view.
return childFocused;
}
private void List_PreviewMouseLeftButtonDown (object Sender, MouseEventArgs E)
{
if (focusCheck() == false) // add this to each event you want to toggle activity of.
{
startPoint_ = E.GetPosition (null);
}
}
无论如何,我根本没有测试过这个,但它可以工作。也许它至少可以帮助你思考一个新的方向!