C# 在MVVM中更改CaretIndex时,没有通知我

C# 在MVVM中更改CaretIndex时,没有通知我,c#,wpf,silverlight,xaml,C#,Wpf,Silverlight,Xaml,我知道CaretIndex不是依赖项属性 所以我登记如下: public class TextBoxHelper : TextBox { public static readonly DependencyProperty CaretIndexProperty = DependencyProperty.Register (

我知道CaretIndex不是依赖项属性

所以我登记如下:

 public class TextBoxHelper : TextBox
    {
        public static readonly DependencyProperty CaretIndexProperty
                                    = DependencyProperty.Register
                                        (
                                            "CaretIndex", 
                                            typeof(int), 
                                            typeof(TextBoxHelper),
                                            new FrameworkPropertyMetadata
                                                    (
                                                        0, 
                                                        FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, 
                                                        CaretIndexChanged
                                                    )
                                        );

        public static int GetCaretIndex(DependencyObject obj)
        {
            return (int)obj.GetValue(CaretIndexProperty);
        }

        public static void SetCaretIndex(DependencyObject obj, int value)
        {
            obj.SetValue(CaretIndexProperty, value);
        }

        //public new int CaretIndex
        //{
        //    get { return (int)GetValue(CaretIndexProperty); }
        //    set { SetValue(CaretIndexProperty, value); }
        //}

        protected override void OnTextChanged(TextChangedEventArgs e)
        {
            base.OnTextChanged(e);
            CaretIndex = base.CaretIndex;
        }

        protected override void OnKeyDown(KeyEventArgs e)
        {
            base.OnKeyDown(e);
            CaretIndex = base.CaretIndex;
        }

        protected override void OnKeyUp(KeyEventArgs e)
        {
            base.OnKeyUp(e);
            CaretIndex = base.CaretIndex;
        }

        protected override void OnMouseDown(MouseButtonEventArgs e)
        {
            base.OnMouseDown(e);
            CaretIndex = base.CaretIndex;
        }

        protected override void OnMouseUp(MouseButtonEventArgs e)
        {
            base.OnMouseUp(e);
            CaretIndex = base.CaretIndex;
        }

        private static void CaretIndexChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            if (obj is TextBox)
            {
                ((TextBox)obj).CaretIndex = (int)e.NewValue;
            }
        }
    }
<ComboBox x:Name="cbUnder" ItemsSource="{Binding GroupsAndCorrespondingEffects}" 
    IsEditable="True" SelectedItem="{Binding SelectedGroup, Mode=TwoWay}" 
    Text="{Binding InputValue, UpdateSourceTrigger=PropertyChanged}" TextSearch.TextPath="GroupName" 
    Grid.Column="1" Grid.ColumnSpan="4" Grid.Row="3"
    vm:TextBoxHelper.CaretIndex="{Binding CaretIndex, UpdateSourceTrigger=PropertyChanged}">
    <ComboBox.Resources>
        <DataTemplate DataType="{x:Type vm:GroupAndCorrespondingEffect}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding GroupName}" Width="250">
                    <TextBlock.Style>
                        <Style TargetType="TextBlock">
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding IsHighlighted}" Value="True">
                                    <Setter Property="Foreground" Value="Blue" />
                                    <Setter Property="FontWeight" Value="Bold"/>
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </TextBlock.Style>
                </TextBlock>
                <TextBlock Text="{Binding CorrespondingEffect}" />
            </StackPanel>
        </DataTemplate>
    </ComboBox.Resources>
</ComboBox>
    private int _caretIndex;
    public int CaretIndex
    {
        get { return _caretIndex; }
        set
        {
            _caretIndex = value;
            OnPropertyChanged("CaretIndex");

            if (InputValue != null && CaretIndex >= 0)
            {
                SelectionStart = CaretIndex;
                Debug.WriteLine(string.Format("Selection Start : {0}", SelectionStart));
                SelectionLength = InputValue.Length - CaretIndex;
                Debug.WriteLine(string.Format("Selection Length : {0}", SelectionLength));
            }

            for (int i = 0; i < GroupsAndCorrespondingEffects.Count; i++)
            {

                string WordToSearch = InputValue;

                if (_caretIndex != 0 && _caretIndex > 0)
                {
                    WordToSearch = InputValue.Substring(0, _caretIndex);
                }

                if (WordToSearch != null)
                {
                    GroupsAndCorrespondingEffects[i].IsHighlighted = GroupsAndCorrespondingEffects[i].GroupName.StartsWith(WordToSearch);
                }
            }
        }
    }

    private string _inputValue;
    public string InputValue
    {
        get { return _inputValue; }
        set
        {
            _inputValue = value;
            OnPropertyChanged("GroupsAndCorrespondingEffects");

            if (InputValue != null && CaretIndex >= 0)
            {
                SelectionStart = CaretIndex;
                Debug.WriteLine(string.Format("Selection Start : {0}", SelectionStart));
                SelectionLength = InputValue.Length - CaretIndex;
                Debug.WriteLine(string.Format("Selection Length : {0}", SelectionLength));
            }

            for (int i = 0; i < GroupsAndCorrespondingEffects.Count; i++)
            {

                string WordToSearch = _inputValue;

                if (_caretIndex != 0 && _caretIndex > 0 && _caretIndex < _inputValue.Length)
                {
                    WordToSearch = _inputValue.Substring(0, _caretIndex);
                }

                GroupsAndCorrespondingEffects[i].IsHighlighted = GroupsAndCorrespondingEffects[i].GroupName.StartsWith(WordToSearch);

            }
        }
    }
然后,我在ViewModel中创建了一个名为CaretIndex的属性。它实现INotifyPropertyChanged接口

private int _caretIndex;
public int CaretIndex
{
    get { return _caretIndex; }
    set
    {
        _caretIndex = value;
        OnPropertyChanged("CaretIndex");
    }
}
然后,我在组合框中创建了绑定,如下所示:

 public class TextBoxHelper : TextBox
    {
        public static readonly DependencyProperty CaretIndexProperty
                                    = DependencyProperty.Register
                                        (
                                            "CaretIndex", 
                                            typeof(int), 
                                            typeof(TextBoxHelper),
                                            new FrameworkPropertyMetadata
                                                    (
                                                        0, 
                                                        FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, 
                                                        CaretIndexChanged
                                                    )
                                        );

        public static int GetCaretIndex(DependencyObject obj)
        {
            return (int)obj.GetValue(CaretIndexProperty);
        }

        public static void SetCaretIndex(DependencyObject obj, int value)
        {
            obj.SetValue(CaretIndexProperty, value);
        }

        //public new int CaretIndex
        //{
        //    get { return (int)GetValue(CaretIndexProperty); }
        //    set { SetValue(CaretIndexProperty, value); }
        //}

        protected override void OnTextChanged(TextChangedEventArgs e)
        {
            base.OnTextChanged(e);
            CaretIndex = base.CaretIndex;
        }

        protected override void OnKeyDown(KeyEventArgs e)
        {
            base.OnKeyDown(e);
            CaretIndex = base.CaretIndex;
        }

        protected override void OnKeyUp(KeyEventArgs e)
        {
            base.OnKeyUp(e);
            CaretIndex = base.CaretIndex;
        }

        protected override void OnMouseDown(MouseButtonEventArgs e)
        {
            base.OnMouseDown(e);
            CaretIndex = base.CaretIndex;
        }

        protected override void OnMouseUp(MouseButtonEventArgs e)
        {
            base.OnMouseUp(e);
            CaretIndex = base.CaretIndex;
        }

        private static void CaretIndexChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            if (obj is TextBox)
            {
                ((TextBox)obj).CaretIndex = (int)e.NewValue;
            }
        }
    }
<ComboBox x:Name="cbUnder" ItemsSource="{Binding GroupsAndCorrespondingEffects}" 
    IsEditable="True" SelectedItem="{Binding SelectedGroup, Mode=TwoWay}" 
    Text="{Binding InputValue, UpdateSourceTrigger=PropertyChanged}" TextSearch.TextPath="GroupName" 
    Grid.Column="1" Grid.ColumnSpan="4" Grid.Row="3"
    vm:TextBoxHelper.CaretIndex="{Binding CaretIndex, UpdateSourceTrigger=PropertyChanged}">
    <ComboBox.Resources>
        <DataTemplate DataType="{x:Type vm:GroupAndCorrespondingEffect}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding GroupName}" Width="250">
                    <TextBlock.Style>
                        <Style TargetType="TextBlock">
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding IsHighlighted}" Value="True">
                                    <Setter Property="Foreground" Value="Blue" />
                                    <Setter Property="FontWeight" Value="Bold"/>
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </TextBlock.Style>
                </TextBlock>
                <TextBlock Text="{Binding CorrespondingEffect}" />
            </StackPanel>
        </DataTemplate>
    </ComboBox.Resources>
</ComboBox>
    private int _caretIndex;
    public int CaretIndex
    {
        get { return _caretIndex; }
        set
        {
            _caretIndex = value;
            OnPropertyChanged("CaretIndex");

            if (InputValue != null && CaretIndex >= 0)
            {
                SelectionStart = CaretIndex;
                Debug.WriteLine(string.Format("Selection Start : {0}", SelectionStart));
                SelectionLength = InputValue.Length - CaretIndex;
                Debug.WriteLine(string.Format("Selection Length : {0}", SelectionLength));
            }

            for (int i = 0; i < GroupsAndCorrespondingEffects.Count; i++)
            {

                string WordToSearch = InputValue;

                if (_caretIndex != 0 && _caretIndex > 0)
                {
                    WordToSearch = InputValue.Substring(0, _caretIndex);
                }

                if (WordToSearch != null)
                {
                    GroupsAndCorrespondingEffects[i].IsHighlighted = GroupsAndCorrespondingEffects[i].GroupName.StartsWith(WordToSearch);
                }
            }
        }
    }

    private string _inputValue;
    public string InputValue
    {
        get { return _inputValue; }
        set
        {
            _inputValue = value;
            OnPropertyChanged("GroupsAndCorrespondingEffects");

            if (InputValue != null && CaretIndex >= 0)
            {
                SelectionStart = CaretIndex;
                Debug.WriteLine(string.Format("Selection Start : {0}", SelectionStart));
                SelectionLength = InputValue.Length - CaretIndex;
                Debug.WriteLine(string.Format("Selection Length : {0}", SelectionLength));
            }

            for (int i = 0; i < GroupsAndCorrespondingEffects.Count; i++)
            {

                string WordToSearch = _inputValue;

                if (_caretIndex != 0 && _caretIndex > 0 && _caretIndex < _inputValue.Length)
                {
                    WordToSearch = _inputValue.Substring(0, _caretIndex);
                }

                GroupsAndCorrespondingEffects[i].IsHighlighted = GroupsAndCorrespondingEffects[i].GroupName.StartsWith(WordToSearch);

            }
        }
    }
我试过上面的代码,但它告诉我输入字符串的格式不正确

因此,我将上述代码替换为:

<Style TargetType="ComboBox" BasedOn="{StaticResource {x:Type ComboBox}}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ComboBox">
                <TextBox x:Name="PART_EditableTextBox" vm:TextBoxHelper.CaretIndex="{Binding CaretIndex, UpdateSourceTrigger=PropertyChanged}" />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
更新4

我的ViewModel中还有一个属性InputValue

private string _inputValue;
public string InputValue
{
    get { return _inputValue; }
    set
    {
        _inputValue = value;
        OnPropertyChanged("GroupsAndCorrespondingEffects");

        for (int i = 0; i < GroupsAndCorrespondingEffects.Count; i++)
        {

            string WordToSearch = _inputValue;

            if (_caretIndex != 0 || _caretIndex != null)
            {
                WordToSearch = _inputValue.Substring(0, _caretIndex);
            }

            GroupsAndCorrespondingEffects[i].IsHighlighted = GroupsAndCorrespondingEffects[i].GroupName.StartsWith(WordToSearch);
        }
    }
}
在ViewModel中调用属性的过程如下:

 public class TextBoxHelper : TextBox
    {
        public static readonly DependencyProperty CaretIndexProperty
                                    = DependencyProperty.Register
                                        (
                                            "CaretIndex", 
                                            typeof(int), 
                                            typeof(TextBoxHelper),
                                            new FrameworkPropertyMetadata
                                                    (
                                                        0, 
                                                        FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, 
                                                        CaretIndexChanged
                                                    )
                                        );

        public static int GetCaretIndex(DependencyObject obj)
        {
            return (int)obj.GetValue(CaretIndexProperty);
        }

        public static void SetCaretIndex(DependencyObject obj, int value)
        {
            obj.SetValue(CaretIndexProperty, value);
        }

        //public new int CaretIndex
        //{
        //    get { return (int)GetValue(CaretIndexProperty); }
        //    set { SetValue(CaretIndexProperty, value); }
        //}

        protected override void OnTextChanged(TextChangedEventArgs e)
        {
            base.OnTextChanged(e);
            CaretIndex = base.CaretIndex;
        }

        protected override void OnKeyDown(KeyEventArgs e)
        {
            base.OnKeyDown(e);
            CaretIndex = base.CaretIndex;
        }

        protected override void OnKeyUp(KeyEventArgs e)
        {
            base.OnKeyUp(e);
            CaretIndex = base.CaretIndex;
        }

        protected override void OnMouseDown(MouseButtonEventArgs e)
        {
            base.OnMouseDown(e);
            CaretIndex = base.CaretIndex;
        }

        protected override void OnMouseUp(MouseButtonEventArgs e)
        {
            base.OnMouseUp(e);
            CaretIndex = base.CaretIndex;
        }

        private static void CaretIndexChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            if (obj is TextBox)
            {
                ((TextBox)obj).CaretIndex = (int)e.NewValue;
            }
        }
    }
<ComboBox x:Name="cbUnder" ItemsSource="{Binding GroupsAndCorrespondingEffects}" 
    IsEditable="True" SelectedItem="{Binding SelectedGroup, Mode=TwoWay}" 
    Text="{Binding InputValue, UpdateSourceTrigger=PropertyChanged}" TextSearch.TextPath="GroupName" 
    Grid.Column="1" Grid.ColumnSpan="4" Grid.Row="3"
    vm:TextBoxHelper.CaretIndex="{Binding CaretIndex, UpdateSourceTrigger=PropertyChanged}">
    <ComboBox.Resources>
        <DataTemplate DataType="{x:Type vm:GroupAndCorrespondingEffect}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding GroupName}" Width="250">
                    <TextBlock.Style>
                        <Style TargetType="TextBlock">
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding IsHighlighted}" Value="True">
                                    <Setter Property="Foreground" Value="Blue" />
                                    <Setter Property="FontWeight" Value="Bold"/>
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </TextBlock.Style>
                </TextBlock>
                <TextBlock Text="{Binding CorrespondingEffect}" />
            </StackPanel>
        </DataTemplate>
    </ComboBox.Resources>
</ComboBox>
    private int _caretIndex;
    public int CaretIndex
    {
        get { return _caretIndex; }
        set
        {
            _caretIndex = value;
            OnPropertyChanged("CaretIndex");

            if (InputValue != null && CaretIndex >= 0)
            {
                SelectionStart = CaretIndex;
                Debug.WriteLine(string.Format("Selection Start : {0}", SelectionStart));
                SelectionLength = InputValue.Length - CaretIndex;
                Debug.WriteLine(string.Format("Selection Length : {0}", SelectionLength));
            }

            for (int i = 0; i < GroupsAndCorrespondingEffects.Count; i++)
            {

                string WordToSearch = InputValue;

                if (_caretIndex != 0 && _caretIndex > 0)
                {
                    WordToSearch = InputValue.Substring(0, _caretIndex);
                }

                if (WordToSearch != null)
                {
                    GroupsAndCorrespondingEffects[i].IsHighlighted = GroupsAndCorrespondingEffects[i].GroupName.StartsWith(WordToSearch);
                }
            }
        }
    }

    private string _inputValue;
    public string InputValue
    {
        get { return _inputValue; }
        set
        {
            _inputValue = value;
            OnPropertyChanged("GroupsAndCorrespondingEffects");

            if (InputValue != null && CaretIndex >= 0)
            {
                SelectionStart = CaretIndex;
                Debug.WriteLine(string.Format("Selection Start : {0}", SelectionStart));
                SelectionLength = InputValue.Length - CaretIndex;
                Debug.WriteLine(string.Format("Selection Length : {0}", SelectionLength));
            }

            for (int i = 0; i < GroupsAndCorrespondingEffects.Count; i++)
            {

                string WordToSearch = _inputValue;

                if (_caretIndex != 0 && _caretIndex > 0 && _caretIndex < _inputValue.Length)
                {
                    WordToSearch = _inputValue.Substring(0, _caretIndex);
                }

                GroupsAndCorrespondingEffects[i].IsHighlighted = GroupsAndCorrespondingEffects[i].GroupName.StartsWith(WordToSearch);

            }
        }
    }
现在,当我在组合框中键入第一个字符时:

CaretIndex = 0

CaretIndex = 0

InputValue = Text of combobox

CaretIndex = 1

CaretIndex = 1
CaretIndex = 1

InputValue = Text of combobox

CaretIndex = 2
CaretIndex = 2

InputValue = Text of combobox

CaretIndex = 3
在组合框中键入第二个字符时:

CaretIndex = 0

CaretIndex = 0

InputValue = Text of combobox

CaretIndex = 1

CaretIndex = 1
CaretIndex = 1

InputValue = Text of combobox

CaretIndex = 2
CaretIndex = 2

InputValue = Text of combobox

CaretIndex = 3
在组合框中键入第三个字符时:

CaretIndex = 0

CaretIndex = 0

InputValue = Text of combobox

CaretIndex = 1

CaretIndex = 1
CaretIndex = 1

InputValue = Text of combobox

CaretIndex = 2
CaretIndex = 2

InputValue = Text of combobox

CaretIndex = 3
等等

我在combobox中突出显示项目的逻辑基于CaretIndex中的更改。此逻辑写入
InputValue
属性的set部分。但是由于上面提到的事实,在CaretIndex获取新值之前调用InputValue,我得到了不正确的突出显示

更新5-保留选择丢失

我在TextBoxHelper类中添加了SelectionStart和SelectionLength属性,因为它们不是依赖属性

代码如下:

    public static readonly DependencyProperty BindableSelectionStartProperty
                    = DependencyProperty.RegisterAttached
                        (
                            "BindableSelectionStart",
                            typeof(int),
                            typeof(TextBoxHelper),
                            new PropertyMetadata
                                    (
                                        BindableSelectionStartChanged
                                    )
                        );

    public static readonly DependencyProperty BindableSelectionLengthProperty
                    = DependencyProperty.RegisterAttached
                        (
                            "BindableSelectionLength",
                            typeof(int),
                            typeof(TextBoxHelper),
                            new PropertyMetadata
                                    (
                                        BindableSelectionLengthChanged
                                    )
                        );

    public static int GetBindableSelectionStart(DependencyObject obj)
    {
        return (int)obj.GetValue(BindableSelectionStartProperty);
    }

    public static void SetBindableSelectionStart(DependencyObject obj, int value)
    {
        obj.SetValue(BindableSelectionStartProperty, value);
    }

    public int BindableSelectionStart
    {
        get
        {
            return (int)this.GetValue(BindableSelectionStartProperty);
        }
        set
        {
            this.SetValue(BindableSelectionStartProperty, value);
        }
    }

    public static int GetBindableSelectionLength(DependencyObject obj)
    {
        return (int)obj.GetValue(BindableSelectionLengthProperty);
    }

    public static void SetBindableSelectionLength(DependencyObject obj, int value)
    {
        obj.SetValue(BindableSelectionLengthProperty, value);
    }

    public int BindableSelectionLength
    {
        get
        {
            return (int)this.GetValue(BindableSelectionLengthProperty);
        }
        set
        {
            this.SetValue(BindableSelectionLengthProperty, value);
        }
    }

    private static void BindableSelectionStartChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is TextBox)
        {
            ((TextBox)d).SelectionStart = (int)e.NewValue;
        }
    }

    private static void BindableSelectionLengthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is TextBox)
        {
            ((TextBox)d).SelectionLength = (int)e.NewValue;
        }
    }

    protected override void OnSelectionChanged(RoutedEventArgs e)
    {
        base.OnSelectionChanged(e);
        BindableSelectionStart = base.SelectionStart;
        BindableSelectionLength = base.SelectionLength;
    }
public sealed class TextBoxHelper: TextBox
{
    public static readonly DependencyProperty MyCaretIndexProperty
                                = DependencyProperty.Register
                                    (
                                        "MyCaretIndex", 
                                        typeof(int), 
                                        typeof(TextBoxHelper),
                                        new FrameworkPropertyMetadata
                                                (
                                                    0, 
                                                    FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, 
                                                    MyCaretIndexChanged
                                                )
                                    );

    public static int GetMyCaretIndex(DependencyObject obj)
    {
        return (int)obj.GetValue(MyCaretIndexProperty);
    }

    public static void SetMyCaretIndex(DependencyObject obj, int value)
    {
        obj.SetValue(MyCaretIndexProperty, value);
    }

    public int MyCaretIndex
    {
        get { return (int)GetValue(MyCaretIndexProperty); }
        set { SetValue(MyCaretIndexProperty, value); }
    }

    protected override void OnTextChanged(TextChangedEventArgs e)
    {
        base.OnTextChanged(e);
        MyCaretIndex = base.CaretIndex;
    }

    protected override void OnKeyDown(KeyEventArgs e)
    {
        base.OnKeyDown(e);
        MyCaretIndex = base.CaretIndex;
    }

    protected override void OnKeyUp(KeyEventArgs e)
    {
        base.OnKeyUp(e);
        MyCaretIndex = base.CaretIndex;
    }

    protected override void OnMouseDown(MouseButtonEventArgs e)
    {
        base.OnMouseDown(e);
        MyCaretIndex = base.CaretIndex;
    }

    protected override void OnMouseUp(MouseButtonEventArgs e)
    {
        base.OnMouseUp(e);
        MyCaretIndex = base.CaretIndex;
    }

    private static void MyCaretIndexChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        if (obj is TextBox)
        {
            ((TextBox)obj).CaretIndex = (int)e.NewValue;
        }
    }
}
然后,我在ViewModel中创建了相应的属性

    private int _selectionStart;
    public int SelectionStart
    {
        get
        {
            return _selectionStart;
        }
        set
        {
            _selectionStart = value;
            OnPropertyChanged("SelectionStart");
        }
    }

    private int _selectionLength;
    public int SelectionLength
    {
        get
        {
            return _selectionLength;
        }
        set
        {
            _selectionLength = value;
            OnPropertyChanged("SelectionLength");
        }
    }
之后,我更改了ViewModel的
CaretIndex
InputValue
属性,如下所示:

 public class TextBoxHelper : TextBox
    {
        public static readonly DependencyProperty CaretIndexProperty
                                    = DependencyProperty.Register
                                        (
                                            "CaretIndex", 
                                            typeof(int), 
                                            typeof(TextBoxHelper),
                                            new FrameworkPropertyMetadata
                                                    (
                                                        0, 
                                                        FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, 
                                                        CaretIndexChanged
                                                    )
                                        );

        public static int GetCaretIndex(DependencyObject obj)
        {
            return (int)obj.GetValue(CaretIndexProperty);
        }

        public static void SetCaretIndex(DependencyObject obj, int value)
        {
            obj.SetValue(CaretIndexProperty, value);
        }

        //public new int CaretIndex
        //{
        //    get { return (int)GetValue(CaretIndexProperty); }
        //    set { SetValue(CaretIndexProperty, value); }
        //}

        protected override void OnTextChanged(TextChangedEventArgs e)
        {
            base.OnTextChanged(e);
            CaretIndex = base.CaretIndex;
        }

        protected override void OnKeyDown(KeyEventArgs e)
        {
            base.OnKeyDown(e);
            CaretIndex = base.CaretIndex;
        }

        protected override void OnKeyUp(KeyEventArgs e)
        {
            base.OnKeyUp(e);
            CaretIndex = base.CaretIndex;
        }

        protected override void OnMouseDown(MouseButtonEventArgs e)
        {
            base.OnMouseDown(e);
            CaretIndex = base.CaretIndex;
        }

        protected override void OnMouseUp(MouseButtonEventArgs e)
        {
            base.OnMouseUp(e);
            CaretIndex = base.CaretIndex;
        }

        private static void CaretIndexChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            if (obj is TextBox)
            {
                ((TextBox)obj).CaretIndex = (int)e.NewValue;
            }
        }
    }
<ComboBox x:Name="cbUnder" ItemsSource="{Binding GroupsAndCorrespondingEffects}" 
    IsEditable="True" SelectedItem="{Binding SelectedGroup, Mode=TwoWay}" 
    Text="{Binding InputValue, UpdateSourceTrigger=PropertyChanged}" TextSearch.TextPath="GroupName" 
    Grid.Column="1" Grid.ColumnSpan="4" Grid.Row="3"
    vm:TextBoxHelper.CaretIndex="{Binding CaretIndex, UpdateSourceTrigger=PropertyChanged}">
    <ComboBox.Resources>
        <DataTemplate DataType="{x:Type vm:GroupAndCorrespondingEffect}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding GroupName}" Width="250">
                    <TextBlock.Style>
                        <Style TargetType="TextBlock">
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding IsHighlighted}" Value="True">
                                    <Setter Property="Foreground" Value="Blue" />
                                    <Setter Property="FontWeight" Value="Bold"/>
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </TextBlock.Style>
                </TextBlock>
                <TextBlock Text="{Binding CorrespondingEffect}" />
            </StackPanel>
        </DataTemplate>
    </ComboBox.Resources>
</ComboBox>
    private int _caretIndex;
    public int CaretIndex
    {
        get { return _caretIndex; }
        set
        {
            _caretIndex = value;
            OnPropertyChanged("CaretIndex");

            if (InputValue != null && CaretIndex >= 0)
            {
                SelectionStart = CaretIndex;
                Debug.WriteLine(string.Format("Selection Start : {0}", SelectionStart));
                SelectionLength = InputValue.Length - CaretIndex;
                Debug.WriteLine(string.Format("Selection Length : {0}", SelectionLength));
            }

            for (int i = 0; i < GroupsAndCorrespondingEffects.Count; i++)
            {

                string WordToSearch = InputValue;

                if (_caretIndex != 0 && _caretIndex > 0)
                {
                    WordToSearch = InputValue.Substring(0, _caretIndex);
                }

                if (WordToSearch != null)
                {
                    GroupsAndCorrespondingEffects[i].IsHighlighted = GroupsAndCorrespondingEffects[i].GroupName.StartsWith(WordToSearch);
                }
            }
        }
    }

    private string _inputValue;
    public string InputValue
    {
        get { return _inputValue; }
        set
        {
            _inputValue = value;
            OnPropertyChanged("GroupsAndCorrespondingEffects");

            if (InputValue != null && CaretIndex >= 0)
            {
                SelectionStart = CaretIndex;
                Debug.WriteLine(string.Format("Selection Start : {0}", SelectionStart));
                SelectionLength = InputValue.Length - CaretIndex;
                Debug.WriteLine(string.Format("Selection Length : {0}", SelectionLength));
            }

            for (int i = 0; i < GroupsAndCorrespondingEffects.Count; i++)
            {

                string WordToSearch = _inputValue;

                if (_caretIndex != 0 && _caretIndex > 0 && _caretIndex < _inputValue.Length)
                {
                    WordToSearch = _inputValue.Substring(0, _caretIndex);
                }

                GroupsAndCorrespondingEffects[i].IsHighlighted = GroupsAndCorrespondingEffects[i].GroupName.StartsWith(WordToSearch);

            }
        }
    }
private int\u caretIndex;
公共int CaretIndex
{
获取{return\u caretIndex;}
设置
{
_caretIndex=值;
OnPropertyChanged(“CaretIndex”);
if(InputValue!=null&&CaretIndex>=0)
{
SelectionStart=CaretIndex;
Debug.WriteLine(string.Format(“选择开始:{0}”,选择开始));
SelectionLength=InputValue.Length-CaretIndex;
WriteLine(string.Format(“选择长度:{0}”,SelectionLength));
}
对于(int i=0;i0)
{
WordToSearch=InputValue.Substring(0,_caretIndex);
}
if(WordToSearch!=null)
{
GroupsAndCorrespondingEffects[i]。IsHighlighted=GroupsAndCorrespondingEffects[i]。GroupName.StartsWith(WordToSearch);
}
}
}
}
私有字符串_inputValue;
公共字符串输入值
{
获取{return}inputValue;}
设置
{
_输入值=值;
关于财产变更(“集团和相应影响”);
if(InputValue!=null&&CaretIndex>=0)
{
SelectionStart=CaretIndex;
Debug.WriteLine(string.Format(“选择开始:{0}”,选择开始));
SelectionLength=InputValue.Length-CaretIndex;
WriteLine(string.Format(“选择长度:{0}”,SelectionLength));
}
对于(int i=0;i0&&u caretIndex<\u inputValue.Length)
{
WordToSearch=\u inputValue.Substring(0,\u caretIndex);
}
GroupsAndCorrespondingEffects[i]。IsHighlighted=GroupsAndCorrespondingEffects[i]。GroupName.StartsWith(WordToSearch);
}
}
}
我在ResourceDictionary中做的最后一次更改如下:

<vm:TextBoxHelper x:Name="PART_EditableTextBox" MyCaretIndex="{Binding CaretIndex}" 
                                                BindableSelectionStart="{Binding SelectionStart}"
                                                BindableSelectionLength="{Binding SelectionLength}"
...........                                    

将问题与代码结合起来:

1) 通过在
TextBoxHelper
中执行
CaretIndex=base.CaretIndex
,您实际上是在设置相同的属性,该属性不会触发或更改任何内容

2) 您正在设置
ComboBox
默认模板,但当
IsEditable
为true时,您要设置的是ComboBox模板。否则,WPF会将您提供的模板作为默认模板,一旦您将IsEditable设置为true,WPF就会引入默认的可编辑模板,该模板使用TextBox,而不是用户TextBoxHelper

所以,这就是我所做的工作:

1) 已更新组合框样式,仅当
IsEditable
True

<Style TargetType="ComboBox" BasedOn="{StaticResource {x:Type ComboBox}}">
    <Style.Triggers>
        <Trigger Property="IsEditable" Value="True">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ComboBox">
                        <local:TextBoxHelper x:Name="PART_EditableTextBox" MyCaretIndex="{Binding CaretIndex}" />
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Trigger>
    </Style.Triggers>
</Style>
以及CaretIndex属性的my ViewModel代码供您参考:

public int CaretIndex
{
    get { return _caretIndex; }
    set
    {
        _caretIndex = value;
        Trace.WriteLine(String.Format("Caret Index {0}", _caretIndex));
        if(PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs("CaretIndex"));
    }
}
查看代码:

<ComboBox ItemsSource="{Binding Items}" IsEditable="True" />
更新2

<TextBox x:Name="PART_EditableTextBox" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" IsReadOnly="{Binding IsReadOnly, RelativeSource={RelativeSource TemplatedParent}}" Margin="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}">
                <TextBox.Style>
                    <Style TargetType="{x:Type TextBox}">
                        <Setter Property="vm:TextBoxHelper.CaretIndex" Value="{Binding CaretIndex, UpdateSourceTrigger=PropertyChanged}" />
            .
.
.
修复所选文本丢失问题:

TextBoxHelper
中的MyCaretIndexChanged方法更新为:

private static void MyCaretIndexChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
    if (obj is TextBox && (int)e.OldValue != (int)e.NewValue)
    {
        var textBox = (TextBox) obj;
        textBox.CaretIndex = (int)e.NewValue;
        if (!string.IsNullOrEmpty(textBox.Text))
            textBox.Select(textBox.CaretIndex, textBox.Text.Length - textBox.CaretIndex);
    }
}

你有子类
TextBox
来创建新的DP,但是combobox仍然在里面使用WPF TextBox。我现在可以做什么,让combobox使用我的子类?你必须覆盖combobox的
模板
。你能给我一个链接到覆盖模板的任何教程/示例吗?如果可以,请发布我如何获得其他部分的内容组合框。我已将您更新的代码放入资源字典中。但是当CaretIndex发生变化时,我没有得到通知。我需要在组合框中引用资源字典吗?如果是,那么如何操作?您需要将resourcedictionary包含在您拥有组合框的usercontrol中。e、 g代码:
我没有使用UserControl。因此,我已经在App.xaml文件中添加了上述注释中的代码。但是当CaretIndex发生变化时,我没有得到通知。在您更新答案之前,我直接在Combobox.Resources部分中尝试了该代码,它给了我通知。可能有什么问题?我在app.xaml中尝试了更新的代码,结果很好。发布你的app.xaml。另外,当您在调试器下运行应用程序时,在输出窗口中是否看到任何绑定错误?