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
集合? 或者我怎样才能以其他方式实现我的目标?
谢谢你的帮助。
答
由于改变Text
属性的值没有反正重新亮点,因为我无法摆脱提到的问题,我创建了自己的附加属性Text
改变的TextBlock
的Text
财产和触发重新突出。如果我绑定到该属性,而不是TextBlock
中提供的那个,那么现在一切正常。
在C#中,我们正在做类似于: myTextbox.SetCurrentValue(TextProperty,anyValueHere)',这不应该破坏绑定。 – sTrenat
此外,您可以添加绑定切换的文本框样式,例如: –
sTrenat
还有一个:结合,然后再次将其指定,如在C#: 'bindingExpression bindingExpression = myTextbox.GetBindingExpression(TextBox.TextProperty);'' 结合parentBinding = bindingExpression.ParentBinding;'..一些代码来改变突出显示的,然后: 'myTextbox.SetBinding(文本框。TextProperty,parentBinding);' – sTrenat