2

次のコードを XAML として記述する方法

このコードのスニップがあると仮定します

        var myValue = someMethodeReturn(); // the return will fit

        // could also be an other nonbindable property
        var myTextBlock = new TextBlock();
        myTextBlock.Inlines = myValue;

どのように変換しますか

       var myValue = someMethodeReturn(); 

myTextBlock.Inlines = myValue;

XAML のみとして

確かに最初の部分は次のように見え、2番目の部分は次のように見える ???={Binding myProperty} かもしれません<TextBlock.Inlines><???/></TextBlock.Inlines> が、どのよう???に見えるでしょうか?

視覚的な結果は次のようになります (ソリューションを実行した場合)

    <TextBlock  HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="LightGray" TextWrapping="WrapWithOverflow" >
        <TextBlock.Inlines>
            <Run>meine sehr sehr sehr sehr sehr sehr sehr sehr sehr sehr sehr  lange run 1</Run>
            <Run Foreground="Green" FontFamily='Palatino Linotype' Typography.Variants='Superscript'>meine run2</Run>
            <Run>meine sehr sehr sehr sehr sehr sehr sehr sehr sehr sehr sehr  lange run</Run>
            <Run Foreground="LimeGreen" Background="Yellow">meine run3</Run>
            <Run>meine sehr sehr sehr sehr sehr sehr sehr sehr sehr sehr sehr  lange run</Run>
        </TextBlock.Inlines>
    </TextBlock>

ItemsControlタグ間でテストしましTextBlock.Inlinesたが、デフォルトとして TextBlocks が返され、設定できませんでしたRunInLineItemTemplate

aControlを返す aだけが必要だと思いますが、どれがこれを実行できるList<Inline>かわかりませんControl

任意の提案をいただければ幸いです

私は次の考えを試しました

初め

<TextBlock  HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="LightGray" TextWrapping="WrapWithOverflow" >
    <TextBlock.Inlines>
        <ContentControl Content="{Binding myBinding}"/>
    </TextBlock.Inlines>
</TextBlock>

"(Auflistung)" をテキストとして返す

セカンド

    <TextBlock  HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="LightGray" TextWrapping="WrapWithOverflow" >
        <TextBlock.Inlines>
            <ItemsControl ItemsSource="{Binding myBinding}"/>
        </TextBlock.Inlines>
    </TextBlock>

でラップされた TextBoxes のリストを返しますContenPresenter

4

3 に答える 3

1

文字列値を追加するには、次を使用できます

myTextBlock.Inlines.Add(new Run(myValue));

myValueが配列ループである場合、複数の実行要素を追加します

RunクラスのMsdnドキュメントhttp://msdn.microsoft.com/en-us/library/system.windows.documents.run.aspx

于 2013-03-08T14:42:45.033 に答える
1

次のように、バインド可能なInlines添付プロパティを作成します。

Bindable.cs

using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;

namespace WpfApplication
{
    public static class Bindable
    {
        public static readonly DependencyProperty InlinesProperty = DependencyProperty.RegisterAttached("Inlines", typeof(IEnumerable<Inline>), typeof(Bindable), new PropertyMetadata(OnInlinesChanged));

        private static void OnInlinesChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
        {
            var textBlock = source as TextBlock;

            if (textBlock != null)
            {
                textBlock.Inlines.Clear();
                var inlines = e.NewValue as IEnumerable<Inline>;
                if (inlines != null)
                    textBlock.Inlines.AddRange(inlines);
            }
        }

        [AttachedPropertyBrowsableForType(typeof(TextBlock))]
        public static IEnumerable<Inline> GetInlines(this TextBlock textBlock)
        {
            return (IEnumerable<Inline>)textBlock.GetValue(InlinesProperty);
        }

        public static void SetInlines(this TextBlock textBlock, IEnumerable<Inline> inlines)
        {
            textBlock.SetValue(InlinesProperty, inlines);
        }
    }
}

そして、次のように使用します。

MyViewModel.cs

using System.Collections.Generic;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;

namespace WpfApplication
{
    public class MyViewModel
    {
        // This is against MVVM principle - to contain views (Inlines) in view model, but I don't want to complicate by creating ViewModel class for each Inline derived class.
        public IEnumerable<Inline> Inlines { get; private set; }

        public MyViewModel()
        {
            this.Inlines = new Inline[]
            {
                new Run("meine sehr sehr sehr sehr sehr sehr sehr sehr sehr sehr sehr  lange run 1"),
                new Run("meine run2") { Foreground = Brushes.Green, Typography = { Variants = FontVariants.Superscript } },
                new Run("meine sehr sehr sehr sehr sehr sehr sehr sehr sehr sehr sehr  lange run"),
                new Run("meine run3") { Foreground = Brushes.LimeGreen, Background = Brushes.Yellow },
                new Run("meine sehr sehr sehr sehr sehr sehr sehr sehr sehr sehr sehr  lange run")
            };
        }
    }
}

MainWindow.xaml

<Window x:Class="WpfApplication.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication">
    <Window.DataContext>
        <local:MyViewModel/>
    </Window.DataContext>
    <TextBlock local:Bindable.Inlines="{Binding Inlines}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="LightGray" TextWrapping="WrapWithOverflow"/>
</Window>
于 2013-03-11T23:09:53.710 に答える
1

私のアイデアは、ItemsControl を使用し、ItemPanel を WrapPanel に設定してから、各項目に TextBlocks または ContentPresenters を挿入することでした。これらの TextBlocks は、期待したほどうまく折り返されないことがわかりました。

ここに画像の説明を入力

少なくとも ViewModel はあるので、テキスト項目をソース コレクションにコミットする前に肉挽き機にかけてみませんか? 直後に見えます:

ここに画像の説明を入力

それが正しいと感じるだけなら;)!たぶん、少なくともその一部を使用できます。

ビューモデル:

public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    private ObservableCollection<MyRunModel> _myRuns = new ObservableCollection<MyRunModel>();
    public ObservableCollection<MyRunModel> MyRuns { get { return _myRuns; } set { _myRuns = value; OnPropertyChanged("MyRuns"); } }


    public ViewModel()
    {
        List<MyRunModel> runs = new List<MyRunModel>();
        runs.Add(new MyRunModel() { Text = "Meine sehr sehr sehr sehr sehr sehr sehr sehr sehr sehr sehr lange run1" });
        runs.Add(new MyRunModel() { Text = "Meine run2", Foreground = ForegroundDescription.HighlightDark });
        runs.Add(new MyRunModel() { Text = "Meine sehr sehr sehr sehr sehr sehr sehr sehr sehr sehr sehr lange run3" });
        runs.Add(new MyRunModel() { Text = "Meine run4", Foreground = ForegroundDescription.HighlightLight, Background = BackgroundDescription.Highlight });
        runs.Add(new MyRunModel() { Text = "Meine sehr sehr sehr sehr sehr sehr sehr sehr sehr sehr sehr lange run5" });

        CommitMyRuns(runs);
    }

    /// <summary>
    /// Splits up every run into words (delimited by space), and adds the parts 
    /// to the collection that can be bound to the UI. Retains formatting information.
    /// </summary>
    /// <param name="runs"></param>
    private void CommitMyRuns(List<MyRunModel> runs)
    {
        int runCount = runs.Count;
        for (int i = 0; i < runCount; i++)
        {
            string[] parts = runs[i].Text.Split(' ');
            int partCount = parts.Length;
            for (int j = 0; j < partCount; j++)
            {
                bool isLast = j == parts.Length - 1;
                MyRunModel run = new MyRunModel()
                {
                    Text = parts[j] + (isLast ? string.Empty : " "),  // add space that was lost in split
                    Foreground = runs[i].Foreground, // keep formatting
                    Background = runs[i].Background
                };
                MyRuns.Add(run);
            }
            MyRuns.Add(new MyRunModel() { Text = " " }); // add a space after each of the original runs (unformatted)
        }
    }

}
public class MyRunModel
{
    public string Text { get; set; }
    // do not use UI types (e.g. Brush) directly in viewmodel
    public ForegroundDescription Foreground { get; set; }
    public BackgroundDescription Background { get; set; }
}

public enum ForegroundDescription
{
    None = 0,
    HighlightDark,
    HighlightLight
}

public enum BackgroundDescription
{
    None = 0,
    Highlight
}

Xaml:

<Window.DataContext>
    <local:ViewModel />
</Window.DataContext>

<Window.Resources>
    <SolidColorBrush x:Key="ForegroundHighlightDarkBrush" Color="Green" />
    <SolidColorBrush x:Key="ForegroundHighlightLightBrush" Color="LimeGreen" />
    <SolidColorBrush x:Key="BackgroundHighlightBrush" Color="Yellow" />
</Window.Resources>

<Grid>
    <TextBlock>
        <TextBlock.Inlines>
            <ItemsControl ItemsSource="{Binding MyRuns}" HorizontalContentAlignment="Stretch">
                <ItemsControl.ItemTemplate>
                    <DataTemplate DataType="{x:Type local:MyRunModel}">
                        <TextBlock x:Name="presenter" TextWrapping="Wrap" Text="{Binding Text}"/>
                        <DataTemplate.Triggers>
                            <DataTrigger Binding="{Binding Foreground}" Value="HighlightDark">
                                <Setter TargetName="presenter" Property="TextElement.Foreground" Value="{StaticResource ForegroundHighlightDarkBrush}" />
                            </DataTrigger>
                            <DataTrigger Binding="{Binding Foreground}" Value="HighlightLight">
                                <Setter TargetName="presenter" Property="TextElement.Foreground" Value="{StaticResource ForegroundHighlightLightBrush}" />
                            </DataTrigger>
                            <DataTrigger Binding="{Binding Background}" Value="Highlight">
                                <Setter TargetName="presenter" Property="TextElement.Background" Value="{StaticResource BackgroundHighlightBrush}" />
                            </DataTrigger>
                        </DataTemplate.Triggers>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel Orientation="Horizontal" />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>
        </TextBlock.Inlines>
    </TextBlock>
</Grid>

インラインをバインド可能にするためにテキストボックスをサブクラス化する可能性があります。この回答を参照してください。

于 2013-03-11T21:35:23.193 に答える