C# 如何将xaml中的值适配到不可绑定属性
如何将以下代码编写为XAML 假设我们有这段代码C# 如何将xaml中的值适配到不可绑定属性,c#,wpf,xaml,mvvm,C#,Wpf,Xaml,Mvvm,如何将以下代码编写为XAML 假设我们有这段代码 var myValue = someMethodeReturn(); // the return will fit // could also be an other nonbindable property var myTextBlock = new TextBlock(); myTextBlock.Inlines = myValue; 你将如何转换 var my
var myValue = someMethodeReturn(); // the return will fit
// could also be an other nonbindable property
var myTextBlock = new TextBlock();
myTextBlock.Inlines = myValue;
你将如何转换
var myValue = someMethodeReturn();
及
仅作为XAML
当然,第一部分可能看起来像?={Binding myProperty}
以及类似于
的secound部分,以添加您可以使用的字符串值
myTextBlock.Inlines.Add(new Run(myValue));
如果myValue是数组,则循环并添加多个运行元素
运行类的Msdn文档我的想法是使用ItemsControl并将ItemPanel设置为WrapPanel,然后为每个项目插入文本块或ContentPresenter。事实证明,这些文本块不会像我预期的那样包装得很好:
好吧,您至少有一个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
}
公共类视图模型:INotifyPropertyChanged
{
公共事件属性更改事件处理程序属性更改;
私有void OnPropertyChanged(字符串propertyName)
{
if(this.PropertyChanged!=null)
PropertyChanged(这是新的PropertyChangedEventArgs(propertyName));
}
私有ObservableCollection _myRuns=新ObservableCollection();
公共ObservableCollection MyRuns{get{return{uMyRuns;}set{{uMyRuns=value;OnPropertyChanged(“MyRuns”);}
公共视图模型()
{
列表运行=新建列表();
添加(新的MyRunModel(){Text=“Meine sehr sehr sehr sehr sehr sehr sehr sehr sehr sehr lange run1”});
添加(新的MyRunModel(){Text=“Meine run2”,前台=ForegroundDescription.HighlightDark});
添加(新的MyRunModel(){Text=“Meine sehr sehr sehr sehr sehr sehr sehr sehr sehr sehr lange run3”});
添加(新的MyRunModel(){Text=“Meine run4”,前台=ForegroundDescription.Highlight,后台=BackgroundDescription.Highlight});
添加(新的MyRunModel(){Text=“Meine sehr sehr sehr sehr sehr sehr sehr sehr sehr sehr lange run5”});
委员会(运行);
}
///
///将每次运行拆分为单词(由空格分隔),并添加部分
///指向可绑定到UI的集合。保留格式信息。
///
///
私人作废佣金(列表运行)
{
int runCount=runs.Count;
对于(int i=0;i
Xaml:
子类化文本框以使内联线可绑定可能是一种可能性。请参见。创建可绑定的内联线
附加属性,如下所示:
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);
}
}
}
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")
};
}
}
}
使用System.Collections.Generic;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Documents;
命名空间WpfApplication
{
公共静态类可绑定
{
public static readonly dependencProperty InlinesProperty=dependencProperty.RegisterAttached(“Inlines”、typeof(IEnumerable)、typeof(Bindable)、new PropertyMetadata(OnInlinesChanged));
InLinesChanged上的私有静态无效(DependencyObject源,DependencyPropertyChangedEventArgs e)
{
var textBlock=源作为textBlock;
if(textBlock!=null)
{
textBlock.Inlines.Clear();
var inlines=e.NewValue作为IEnumerable;
如果(内联线!=null)
textBlock.Inlines.AddRange(Inlines);
}
}
[AttachedPropertyBrowsableForType(typeof(TextBlock))]
公共静态IEnumerable GetInlines(此TextBlock TextBlock)
{
return(IEnumerable)textBlock.GetValue(InlinesProperty);
}
公共静态void SetInlines(此TextBlock TextBlock,IEnumerable inlines)
{
设置值(InlinesProperty,inlines);
}
}
}
然后像这样使用它:
MyViewModel.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);
}
}
}
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")
};
}
}
}
使用System.Collections.Generic;
使用System.Windows;
使用System.Windows.Documents;
使用System.Windows.Media;
命名空间WpfApplication
{
公共类MyViewModel
{
<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>
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);
}
}
}
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")
};
}
}
}
<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>