2014-02-19 249 views
3

我的問題與此類似:WPF Generate TextBlock Inlines但我沒有足夠的評論聲望。這裏是附加屬性類:將文本綁定到附加屬性

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" /> 

但是,當我啓動程序時,我在文本塊中什麼也沒有。我也想將文本綁定到我的視圖模型上的一個屬性,但最終想獲得一些東西...

對不起,這可能是一個新手問題,但我不明白爲什麼它不工作。它不會給我任何錯誤,只是不顯示。如果我嘗試綁定,它給我的錯誤:

{"A 'Binding' cannot be set on the 'SetFormattedText' property of type 'TextBlock'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject."}

+0

在StackOverflow上,你*應該*提問的問題,並*不*的意見和它的好,你提供了一個鏈接到的其他問題。但是,您需要提供* [重現問題所需的所有相關代碼](http://stackoverflow.com/help/mcve)*,因爲這是社區可能決定刪除您的問題的原因之一。 – Sheridan

+0

好的不好意思,謝謝指點。我更新了包含我正在嘗試使用的類的源代碼,以及我想要使用它的更多細節... – sfaust

回答

4

首先,屬性的類型必須是一個類的名稱,而不是類型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>"; 
    } 
} 

This example is available at this link .

+0

我很抱歉,我沒有忽略你,只是被拉開放出了火,現在又回到了這一點。謝謝你對理解正在發生的事情非常有幫助。但是,這需要您按下按鈕才能將文本設置爲新值。我真正需要的是將值綁定到我的視圖模型上的屬性,這可能會在界面打開時更改。我不明白我能做到這一點......有可能嗎?此外,我正在upvoting一個非常有用的答案,但沒有標記爲答案,因爲我正在尋找綁定件... – sfaust

+0

@sfaust:請參閱我的編輯。 –

+0

太棒了,標記爲答案!我下載了你的例子,唯一的奇怪之處在於它一直給我兩個自定義命名空間的'未定義的CLR命名空間'錯誤。我檢查了他們,他們似乎是正確的,所以我不知道爲什麼。它建立和功能很好,但不知道爲什麼設計師顯示這些錯誤... – sfaust