C# 在ListView中使用组合框时出现的问题

C# 在ListView中使用组合框时出现的问题,c#,wpf,user-interface,combobox,scrollviewer,C#,Wpf,User Interface,Combobox,Scrollviewer,我有一个列表视图,它显示了许多元素。根据元素的类型,选择正确的DataTemplate来显示它们。其中一个模板用于在组合框中呈现的项目列表 数据模板 <DataTemplate x:Key="comboBoxTemplate0"> <ComboBox ItemsSource="{Binding options}" ToolTip="{Binding Title}" Margin="2" MinWidth="5

我有一个
列表视图
,它显示了许多元素。根据元素的类型,选择正确的
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>
鼠标移动

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);
      }
    }
  }
排水剂

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);
        }
      }
    }
  }
private void List\u Drop(对象发送方,DragEventArgs E)
{
if(例如Data.GetDataPresent(Strings.DragnDropFormatString))
{
CSettingBase Data=E.Data.GetData(Strings.DragnDropFormatString)作为CSettingBase;
if(LoadedSettings.FirstOrDefault(s=>s.Name==Data.Name)==null)
{
加载设置。添加(数据);
Utility.AutoSizeGridViewColumns(ListViewControl);
这是HideColumns(8);
if(((ObservableCollection)this.ListViewControl.ItemsSource).FirstOrDefault(x=>x.IsGroup==true)==null)
{
这是第1列;
}
其他的
{
这是第8列;
}
}
}
}
表演表演

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);
    }
  }
public void performdragandrop(依赖对象来源,列表视图列表)
{
ListViewItem GridRow=Utility.FindAncestor(原点);
if(GridRow!=null)
{
CSettingBase Data=(CSettingBase)List.ItemContainerGenerator.ItemFromContainer(GridRow);
//初始化拖放操作
DataObject DragData=新数据对象(Strings.DragnDropFormatString,数据);
DragDrop.DoDragDrop(网格行、DragData、DragDropEffects.Move);
}
}

在我看来,问题在于触发的是您的
列表事件*
而不是您的
组合框事件

我认为这是有道理的——除非我遗漏了什么……:)

原因是,它们都是控件,但一个控件包含在另一个控件中。例如,如果您的
列表视图是全屏的,那么每次单击任何内容

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);
  }
}

无论如何,我还没有测试过这个,但它可以工作。也许它至少能帮助你朝着一个新的方向思考

你试过ScrollViewer.CanContentScrol
l到
false
?@Mujahiddudkhan是的,也不起作用。试着看看PreviewMouseWheel是否正在为ComboBox启动(应该启动),我们稍后再回复:)对不起,我是说PreviewDragOver@Natxo不,那个事件不会被解雇。是的,这似乎是根本原因。我仍然不确定如何继续,确切地说,但我现在有了一个起点。@MKII我不确定你从上面的答案推断出什么。是的,很明显,当您在任何内部控件上执行任何mouseleftbutton down或mouse move事件时,listview的事件将被执行,这就是我首先请求事件的原因。问题是我在上面的描述中没有看到任何会影响滚动查看器的代码。这让我相信,对于执行上述事件的scrollviewer/scrollbar,必须有任何样式或行为。在drop事件之后,您没有对控件进行任何操作。@KyloRen好吧,我没想到ListView事件会继续触发,我认为事件必须冒泡,但显然不是。我查过了,错误的事件被触发了。所以,现在我知道出了什么问题,我需要在此基础上找到解决方案。这让我相信scrollviewer发生的意外行为一定是其他代码的原因。如果在您的事件中,您本可以使用控件层次结构顺序执行任何操作,但发生了更改,但您所做的只是ExpandColumns/HideColumns/AutoSizeGridViewColumns等。从名称来看,这些方法不建议任何此类操作。@MKII即使事件在listview级别执行,问题是他们怎么能做出这样的行为。是的,活动应该在哪里是完全不同的问题。但我相信,即使是第二个问题的答案也能纠正你的问题。第一个问题值得研究。
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);
  }
}