WPF:如何更改值并保持绑定

WPF:如何更改值并保持绑定

问题描述:

我正在寻找突出显示TextBlock内容的某些部分的方法。WPF:如何更改值并保持绑定

由于大多数我找到建议写我自己的控制,从TextBlock继承,因为我不喜欢写我自己的额外功能一点一滴控制我试图把该funktionality在连接的解决方案行为,我很成功(所以我认为)。

这里是我的行为的代码:

Public NotInheritable Class TextBlockHighlighting 

    Private Sub New() 
    End Sub 

#Region " HighlightTextProperty " 

    Public Shared HighlightTextProperty As DependencyProperty = DependencyProperty.RegisterAttached("HighlightText", GetType(String), GetType(TextBlockHighlighting), New FrameworkPropertyMetadata(Nothing, New PropertyChangedCallback(AddressOf TextBlockHighlighting.OnHighlightTextPropertyChanged))) 

    <AttachedPropertyBrowsableForType(GetType(TextBlock))> 
    Public Shared Function GetHighlightText(ByVal obj As TextBlock) As String 
     Return obj.GetValue(TextBlockHighlighting.HighlightTextProperty) 
    End Function 

    <AttachedPropertyBrowsableForType(GetType(TextBlock))> 
    Public Shared Sub SetHighlightText(ByVal obj As TextBlock, ByVal value As String) 
     obj.SetValue(TextBlockHighlighting.HighlightTextProperty, value) 
    End Sub 

    Private Shared Sub OnHighlightTextPropertyChanged(ByVal sender As Object, ByVal e As DependencyPropertyChangedEventArgs) 
     Dim tb As TextBlock 

     tb = TryCast(sender, TextBlock) 

     If (tb Is Nothing) Then 
      Throw New InvalidOperationException("Error") 
     End If 

     Call TextBlockHighlighting.Refresh(tb) 
    End Sub 

#End Region 

#Region " HighlightStyleProperty " 

    Public Shared HighlightStyleProperty As DependencyProperty = DependencyProperty.RegisterAttached("HighlightStyle", GetType(Style), GetType(TextBlockHighlighting), New FrameworkPropertyMetadata(Nothing, New PropertyChangedCallback(AddressOf TextBlockHighlighting.OnHighlightStylePropertyChanged))) 

    <AttachedPropertyBrowsableForType(GetType(TextBlock))> 
    Public Shared Function GetHighlightStyle(ByVal obj As TextBlock) As Style 
     Return obj.GetValue(TextBlockHighlighting.HighlightStyleProperty) 
    End Function 

    <AttachedPropertyBrowsableForType(GetType(TextBlock))> 
    Public Shared Sub SetHighlightStyle(ByVal obj As TextBlock, ByVal value As Style) 
     obj.SetValue(TextBlockHighlighting.HighlightStyleProperty, value) 
    End Sub 

    Private Shared Sub OnHighlightStylePropertyChanged(ByVal sender As Object, ByVal e As DependencyPropertyChangedEventArgs) 
     Dim tb As TextBlock 

     tb = TryCast(sender, TextBlock) 

     If (tb Is Nothing) Then 
      Throw New InvalidOperationException("Error") 
     End If 

     Call TextBlockHighlighting.Refresh(tb) 
    End Sub 

#End Region 

    Private Shared Sub Refresh(ByVal sender As TextBlock) 
     Dim highlight As String 
     Dim style As Style 
     Dim oldValue As String 

     oldValue = sender.Text 

     If String.IsNullOrEmpty(sender.Text) Then 
      Exit Sub 
     End If 

     sender.Inlines.Clear() 
     highlight = TextBlockHighlighting.GetHighlightText(sender) 
     style = TextBlockHighlighting.GetHighlightStyle(sender) 

     If (style Is Nothing) Then 
      style = New Style(GetType(Run)) 
      style.Setters.Add(New Setter(Run.BackgroundProperty, Brushes.Green)) 
      style.Setters.Add(New Setter(Run.ForegroundProperty, Brushes.White)) 
     End If 

     If String.IsNullOrEmpty(highlight) OrElse (oldValue.IndexOf(highlight, StringComparison.InvariantCultureIgnoreCase) < 0) Then 
      sender.Text = oldValue 
     Else 
      Dim index As Integer = oldValue.IndexOf(highlight, StringComparison.InvariantCultureIgnoreCase) 
      Dim pos As Integer = 0 

      Do While (index >= 0) 
       Dim t As String 

       t = oldValue.Substring(pos, index - pos) 
       sender.Inlines.Add(t) 
       pos = index 

       t = oldValue.Substring(pos, highlight.Length) 
       sender.Inlines.Add(New Run(t) With {.Style = style}) 
       pos += highlight.Length 
       index = oldValue.IndexOf(highlight, pos, StringComparison.InvariantCultureIgnoreCase) 
      Loop 

      sender.Inlines.Add(New Run(oldValue.Substring(pos))) 
     End If 
    End Sub 

End Class 

这里是我的视图模型(我离开RelayCommand级的代码,代码的填写,我想每个人都在为它的实现)。你甚至可以摆脱它背后调用函数ChangeText代码来代替:

Imports System.ComponentModel 

Public Class MainViewModel 
    Implements INotifyPropertyChanged 

    Private _highlightText As String 
    Private _text As String 
    Private _changeTextCommand As ICommand = New RelayCommand(AddressOf Me.ChangeText) 

    Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged 

    Public Sub New() 
     Me.HighlightText = "lo" 
     _text = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet." 
    End Sub 

    Private Sub OnPropertyChanged(propertyName As String) 
     RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName)) 
    End Sub 

    Public Property HighlightText As String 
     Get 
      Return _highlightText 
     End Get 
     Set(value As String) 
      _highlightText = value 
      Me.OnPropertyChanged("HighlightText") 
     End Set 
    End Property 

    Public ReadOnly Property Text As String 
     Get 
      Return _text 
     End Get 
    End Property 

    Public ReadOnly Property ChangeTextCommand As ICommand 
     Get 
      Return _changeTextCommand 
     End Get 
    End Property 

    Private Sub ChangeText() 
     _text = "This is another text containing the default highlight text ""lo""." 
     Me.OnPropertyChanged("Text") 
    End Sub 

End Class 

最后,这里是我的XAML主窗口:

<Window x:Class="MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:WpfApp2" 
     mc:Ignorable="d" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.DataContext> 
     <local:MainViewModel /> 
    </Window.DataContext> 

    <Window.Resources> 
     <Style x:Key="HightlightStyle" TargetType="Run"> 
      <Setter Property="Background" Value="LightGreen" /> 
      <Setter Property="Foreground" Value="Yellow" /> 
     </Style> 
    </Window.Resources> 

    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="Auto" /> 
     </Grid.RowDefinitions> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="Auto" /> 
      <ColumnDefinition Width="*" /> 
     </Grid.ColumnDefinitions> 

     <Label Grid.Row="0" Grid.Column="0" Content="Hightlight text:" /> 
     <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding HighlightText, UpdateSourceTrigger=PropertyChanged}" /> 

     <TextBlock Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Text="{Binding Text}" TextWrapping="Wrap" 
        local:TextBlockHighlighting.HighlightText="{Binding HighlightText}" 
        local:TextBlockHighlighting.HighlightStyle="{StaticResource HightlightStyle}" /> 

     <Button Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Content="Change text" Margin="100,5" Command="{Binding ChangeTextCommand}" /> 
    </Grid> 
</Window> 

而且这里是我的问题。当我启动这个程序并在没有做任何事情之前按下“更改文本”按钮时,文本就会发生变化(像预期的那样)。

但是,当我启动程序,更改高亮文本(因此突出显示),然后点击“更改文本”按钮,没有任何反应。

很多搜​​索和调试,并试图我认为其中的原因是后,在我的附加行为,我改变Inlines收集TextBlock的,并且打破了绑定到Text财产。

那么,如何在不破坏对Text属性的绑定的情况下更改TextBlock(本身不可绑定)的Inlines集合? 或者我怎样才能以其他方式实现我的目标?

谢谢你的帮助。

+0

在C#中,我们正在做类似于: myTextbox.SetCurrentValue(TextProperty,anyValueHere)',这不应该破坏绑定。 – sTrenat

+0

此外,您可以添加绑定切换的文本框样式,例如: sTrenat

+0

还有一个:结合,然后再次将其指定,如在C#: 'bindingExpression bindingExpression = myTextbox.GetBindingExpression(TextBox.TextProperty);'' 结合parentBinding = bindingExpression.ParentBinding;'..一些代码来改变突出显示的,然后: 'myTextbox.SetBinding(文本框。TextProperty,parentBinding);' – sTrenat

由于改变Text属性的值没有反正重新亮点,因为我无法摆脱提到的问题,我创建了自己的附加属性Text改变的TextBlockText财产和触发重新突出。如果我绑定到该属性,而不是TextBlock中提供的那个,那么现在一切正常。