将文本绑定到附加的属性



我的问题类似于此:WPF生成文本块内联,但我没有足够的声誉发表评论。这是附加的属性类:

public class Attached
{
public static readonly DependencyProperty FormattedTextProperty = DependencyProperty.RegisterAttached(
"FormattedText",
typeof(string),
typeof(TextBlock),
new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.AffectsMeasure));
public static void SetFormattedText(DependencyObject textBlock, string value)
{
textBlock.SetValue(FormattedTextProperty, value);
}
public static string GetFormattedText(DependencyObject textBlock)
{
return (string)textBlock.GetValue(FormattedTextProperty);
}
private static void FormattedTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var textBlock = d as TextBlock;
if (textBlock == null)
{
return;
}
var formattedText = (string)e.NewValue ?? string.Empty;
formattedText = string.Format("<Span xml:space="preserve" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">{0}</Span>", formattedText);
textBlock.Inlines.Clear();
using (var xmlReader = XmlReader.Create(new StringReader(formattedText)))
{
var result = (Span)XamlReader.Load(xmlReader);
textBlock.Inlines.Add(result);
}
}
}

我正在使用这个附加的属性类,并试图将其应用于文本块,以使文本识别视图模型类中字符串中的内联值,如粗体、下划线等。我的文本块中有以下XAML:

<TextBlock Grid.Row="1" Grid.Column="1" TextWrapping="Wrap" my:Attached.FormattedText="test" />

然而,当我启动程序时,我在文本块中什么都没有得到。我还想最终将文本绑定到视图模型上的属性,但希望首先显示一些内容。。。

抱歉,这可能是一个新手问题,但我不明白为什么它不起作用。它没有给我任何错误,只是没有出现。如果我尝试绑定,它会给我错误:

{"不能在'TextBlock'类型的'SetFormattedText'属性上设置'Binding'。只能在DependencyObject的DependencyProperty上设置'Binding'。"}

首先,属性的类型需要是类名,而不是类型TextBlock:

public static readonly DependencyProperty FormattedTextProperty = DependencyProperty.RegisterAttached(
"FormattedText",
typeof(string),
typeof(TextBlock), <----- Here

第二,处理程序没有被调用,它必须在这里注册:

new FrameworkPropertyMetadata(string.Empty, 
FrameworkPropertyMetadataOptions.AffectsMeasure,
YOUR_PropertyChanged_HANDLER)

第三,作为一个工作示例,您需要指定这样的输入字符串:

<Bold>My little text</Bold>

工作示例如下:

XAML

<Window x:Class="InlineTextBlockHelp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:this="clr-namespace:InlineTextBlockHelp"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBlock Name="TestText"
this:AttachedPropertyTest.FormattedText="TestString"
Width="200"
Height="100" 
TextWrapping="Wrap" />
<Button Name="TestButton"
Width="100"
Height="30"
VerticalAlignment="Top"
Content="TestClick" 
Click="Button_Click" />
</Grid>
</Window>

Code-behind

public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
string inlineExpression = "<Bold>Once I saw a little bird, go hop, hop, hop.</Bold>";
AttachedPropertyTest.SetFormattedText(TestText, inlineExpression);
}
}
public class AttachedPropertyTest
{
public static readonly DependencyProperty FormattedTextProperty = DependencyProperty.RegisterAttached(
"FormattedText",
typeof(string),
typeof(AttachedPropertyTest),
new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.AffectsMeasure, FormattedTextPropertyChanged));
public static void SetFormattedText(DependencyObject textBlock, string value)
{
textBlock.SetValue(FormattedTextProperty, value);
}
public static string GetFormattedText(DependencyObject textBlock)
{
return (string)textBlock.GetValue(FormattedTextProperty);
}
private static void FormattedTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var textBlock = d as TextBlock;
if (textBlock == null)
{
return;
}
var formattedText = (string)e.NewValue ?? string.Empty;
formattedText = string.Format("<Span xml:space="preserve" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">{0}</Span>", formattedText);
textBlock.Inlines.Clear();
using (var xmlReader = XmlReader.Create(new StringReader(formattedText)))
{
var result = (Span)XamlReader.Load(xmlReader);
textBlock.Inlines.Add(result);
}
}
}

最初是纯文本,点击Button后会分配到内联文本。

Example for MVVM version

要在MVVM样式中使用此示例,您需要在Model/ViewModel中创建适当的属性,并将其与附加的依赖属性相关联,如下所示:

<TextBlock Name="TestText"
PropertiesExtension:TextBlockExt.FormattedText="{Binding Path=InlineText, 
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
Width="200"
Height="100" 
TextWrapping="Wrap" />

Model/ViewModel中的属性必须支持方法NotifyPropertyChanged

这是一个完整的样本:

AttachedProperty

public class TextBlockExt
{
public static readonly DependencyProperty FormattedTextProperty = DependencyProperty.RegisterAttached(
"FormattedText",
typeof(string),
typeof(TextBlockExt),
new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.AffectsMeasure, FormattedTextPropertyChanged));
public static void SetFormattedText(DependencyObject textBlock, string value)
{
textBlock.SetValue(FormattedTextProperty, value);
}
public static string GetFormattedText(DependencyObject textBlock)
{
return (string)textBlock.GetValue(FormattedTextProperty);
}
private static void FormattedTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var textBlock = d as TextBlock;
if (textBlock == null)
{
return;
}
var formattedText = (string)e.NewValue ?? string.Empty;
formattedText = string.Format("<Span xml:space="preserve" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">{0}</Span>", formattedText);
textBlock.Inlines.Clear();
using (var xmlReader = XmlReader.Create(new StringReader(formattedText)))
{
var result = (Span)XamlReader.Load(xmlReader);
textBlock.Inlines.Add(result);
}
}
}

MainViewModel

public class MainViewModel : NotificationObject
{
private string _inlineText = "";
public string InlineText
{
get
{
return _inlineText;
}
set
{
_inlineText = value;
NotifyPropertyChanged("InlineText");
}
}
}

MainWindow.xaml

<Window x:Class="InlineTextBlockHelp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ViewModels="clr-namespace:InlineTextBlockHelp.ViewModels"
xmlns:PropertiesExtension="clr-namespace:InlineTextBlockHelp.PropertiesExtension"
Title="MainWindow" Height="350" Width="525"
ContentRendered="Window_ContentRendered">
<Window.DataContext>
<ViewModels:MainViewModel />
</Window.DataContext>
<Grid>
<TextBlock Name="TestText"
PropertiesExtension:TextBlockExt.FormattedText="{Binding Path=InlineText, 
      Mode=TwoWay,
      UpdateSourceTrigger=PropertyChanged}"
Width="200"
Height="100" 
TextWrapping="Wrap" />
</Grid>
</Window>

Code-behind (just for test)

public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_ContentRendered(object sender, EventArgs e)
{
MainViewModel mainViewModel = this.DataContext as MainViewModel;
mainViewModel.InlineText = "<Bold>Once I saw a little bird, go hop, hop, hop.</Bold>";
}
}

此示例在此link中可用。

最新更新