• 解决IsEditable="True"的ComboBox在DataGrid中点击一次不能选中行的问题


    此方法很笨拙,并不推荐使用!!!

    此方法很笨拙,并不推荐使用!!!

    此方法很笨拙,并不推荐使用!!!

    事件起因,同事用了公司一个继承ComboBox的的自定义可编辑控件,但是发现这个控件在DataGrid中,当点击第一次的时候,光标到了ComboBox中,但是ComboBox所在的DataGrid行却不被选中,还是在原来的选中行上,这个问题,就导致了一些列问题,引起的问题,我们不做讨论。

    经过测试,发现并不是自定义控件本身的问题,而是ComboBox只要设置了IsEditable="True",并且放在DataGrid中,就会存在这个问题,原因是,焦点在ComboBox内部的Textbox上,而没有在ComboBox自身上,看了下MSDN上的源码,如果设置了IsEditable="True",在Textbox拿到焦点以后,handled就会设置为True

    尝试重写了一下ComboBox的一些事件,但是并不起作用,百度、谷歌都走过了,也没有发现有类似相关的问题,断断续续花了两天时间,没有好的办法,最后,只能笨拙的解决这个问题了。

    先看下效果图:

    “好使的”列就是笨拙方法解决的,“不好使的”列就是正常的ComboBox设置了IsEditable="True"熟悉。通过效果图不难看出我刚才说的问题。 

    <DataGrid x:Name="dgTest" ItemsSource="{Binding MoList}" CanUserAddRows="False" AutoGenerateColumns="False">
                <DataGrid.Columns>
                    <DataGridTemplateColumn Header="好使的" Width="*">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <ComboBox x:Name="cb" IsEditable="True"ItemsSource="{Binding DataContext.DmList,RelativeSource={RelativeSource AncestorType=DataGrid}}" SelectedValue="{Binding Dm2}" SelectedValuePath="Dm" DisplayMemberPath="Dm" Text="{Binding Dm2}" GotFocus="ComboBox_GotFocus"/>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                    <DataGridTemplateColumn Header="不好使的" Width="*">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <ComboBox IsEditable="True" ItemsSource="{Binding DataContext.DmList,RelativeSource={RelativeSource AncestorType=DataGrid}}" SelectedValue="{Binding Dm2}" SelectedValuePath="Dm" DisplayMemberPath="Dm" Text="{Binding Dm2}" />
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                </DataGrid.Columns>
            </DataGrid>
    private void ComboBox_GotFocus(object sender, RoutedEventArgs e)
            {for (int i = 0; i < dgTest.Items.Count; i++)
                {
                    DataGridTemplateColumn templateColumn = dgTest.Columns[0] as DataGridTemplateColumn;
                    FrameworkElement element = templateColumn.GetCellContent(dgTest.Items[i]);
                    if (element!=null)
                    {
                        ComboBox combo = templateColumn.CellTemplate.FindName("cb", element) as ComboBox;
                        if ((ComboBox)sender == combo)
                        {
                            dgTest.SelectedIndex = i;
                        }
                    }
                }
            }

    通过上面的代码,我相信广大的程序猿们能看出,为什么这个方法笨拙了,因为需要给DataGrid设置Name,给ComboBox设置Name、GotFocus,还要写死ComboBox所在的列标。所以,这个方法虽然解决了问题,但是,真心的不推荐大家使用,如果谁有好的方法,希望可以留言,谢谢了。

    同事看到我这段代码以后,有点疑惑,不直接用IsFocused以后,进行判断。

    我们将代码修改为以下的,并在if的位置打上断点,发现,无论点击哪个ComboBox,IsFocused始终是False,这是因为,TextboxFocus以后,直接拦截了,所以,没有办法继续触发。

    希望,有好的解决办法的大神,给个留言,在此十分感谢了,如果,有的朋友,也遇到了这个问题,没有其他好的解决办法的话,不如尝试下,我这个笨拙的方法,最起码是解决问题了。

    推荐此方法!!!

    推荐此方法!!!

    推荐此方法!!!

    这个方法是小丁同学提供的思路,就是在ComboBox的GotFocus事件里查找父,也就是所在的行。 

    public static T GetParentObject<T>(DependencyObject obj, string name) where T : FrameworkElement
            {
                DependencyObject parent = VisualTreeHelper.GetParent(obj);
                while (parent != null)
                {
                    if (parent is T && (((T)parent).Name == name | string.IsNullOrEmpty(name)))
                    {
                        return (T)parent;
                    }
                    parent = VisualTreeHelper.GetParent(parent);
                }
                return null;
            }
    protected override void OnGotFocus(RoutedEventArgs e)
            {
                base.OnGotFocus(e);
                DataGridRow row = FindHelper.GetParentObject<DataGridRow>(this, "");
                row.IsSelected = true;
            }

    写一个控件,继承自ComboBox,然后重写GotFocus,这个好处是可以随意使用,不会定死了。

    但是,需要设置DataGrid的SelectionMode="Single",要不然,点选了了几个,就选中了几个

     
  • 相关阅读:
    [LeetCode]Reverse Linked List II
    [LeetCode]Move Zeroes
    Next Greater Element I
    Keyboard Row
    Number Complement
    SQL语句学习(二)
    SQL语句学习(一)
    jQuery学习(三)
    jQuery学习(二)
    JQuery学习(一)
  • 原文地址:https://www.cnblogs.com/ZXdeveloper/p/9183568.html
Copyright © 2020-2023  润新知