如何在WPF中创建可重用的TextBlock绑定?

时间:2014-08-11 16:23:43

标签: c# wpf xaml

我一直在教自己WPF,而且我还在学习基本概念和术语。如果这个问题的标题没有正确的话,请原谅我。

我有以下XAML,HierarchicalDataTemplate的一部分绑定到ViewModelBase类型的对象:

            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding PrefixStyle.Text}" 
                           FontWeight="{Binding PrefixStyle.Weight}" 
                           Foreground ="{Binding PrefixStyle.Foreground}" 
                           Margin="0,0,3,0"/>                                
                <TextBlock Text="{Binding ValueStyle.Text}" 
                           FontWeight="{Binding ValueStyle.Weight}" 
                           Foreground ="{Binding ValueStyle.Foreground}"
                           Margin="0,0,3,0"/>                     
                <TextBlock Text="{Binding SuffixStyle.Text}" 
                           FontWeight="{Binding SuffixStyle.Weight}" 
                           Foreground ="{Binding SuffixStyle.Foreground}" 
                           Margin="0,0,3,0"/>
                           ... 
            </StackPanel>

ViewModelBase具有XAML中引用的相应属性:

public TextBlockStyle PrefixStyle...
public TextBlockStyle ValueStyle...
public TextBlockStyle SuffixStyle... 


public class TextBlockStyle : INotifyPropertyChanged
{
    public string Text...
    public FontWieght Weight...
    public Brush Foreground 
}

如何在XAML中仅将TextBlockTextBlockStyle的绑定定义为一次,并且不必像上面那样明确绑定每个TextBlock属性?所以我可以为每个TextBlock添加一行:

                <StackPanel Orientation="Horizontal">
                    <TextBlock Source="{Binding PrefixStyle}" />                           
                    <TextBlock Source="{Binding ValueStyle}"  />                    
                    <TextBlock Source="{Binding SuffixStyle}" />
                 ...                                                              
                </StackPanel>

我只是不知道从哪里开始。我需要继承TextBlock吗?使用BindingGroup?

这一定是程序员遇到的常见问题 - 所以如果以前曾经问过这个问题,我很抱歉。我尝试过搜索,但我对WPF这么新,我不知道如何正确地表达我的问题。

2 个答案:

答案 0 :(得分:2)

您使用隐式样式设置&#34; global&#34;整个应用程序的风格。这通常在App.xaml内的ResourceDictionary文件中完成。

<Style TargetType="{x:Type TextBlock}"
       BasedOn="{StaticResource TextBlockStyle}">
    <Setter Property="FontWeight" 
            Value="Bold">
    </Setter>
    <Setter Property="Foreground" 
            Value="Red">
    </Setter>
</Style>

如果您继续使用您关注的方法(我不会),您可以将您的二传手更改为:

<Setter Property="FontWeight" 
        Value="{Binding Weight}">
</Setter>

然后,除非您为控件定义更本地的显式/隐式样式,否则应用程序中的所有TextBlock都将使用该样式。

编辑以详细说明评论:

我还使用TreeViewHierarchicalDataTemplate。以MVVM方式思考,TreeView(父/子)中的每个项目都应该代表某种模型。例如,想想Windows资源管理器。其中的每个项目都是MVVM世界中的FolderDriveFolderDrive不会有不同的字体粗细/颜色/尺寸特征,因为它们的所有视图都相关。

在我们的例子中,你会有这样的东西:

public class BaseItem : ViewModel
{
    public ObservableCollection<BaseItem> Children { .... } 
    public bool IsSelected { .... }
    public string Title { .... } 
}

由于文件夹可以容纳更多文件夹,并且驱动器可以容纳文件夹,您可以这样:

public class DriveVM : BaseItem { }
public class FolderVM : BaseItem { }

你要在Children.Add(new FolderVM(folder));内做DriveVM,这会在驱动器下显示一个文件夹。问题是这可能变得相当复杂。简而言之,我认为继承是使用TreeView的关键。

另一种选择是这样的:

<Style x:Name="PrefixTextBlockStyle"
       TargetType="{x:Type TextBox}">
    <Setter Property="FontWeight"
            Value="Bold" />
    <Setter Property="Foreground"
            Value="Red" />
    <Setter Property="Text"
            Value="{Binding Text}" 
    <Setter Property="Margin"
            Value="0 0 3 0" />
</Style>
<Style x:Name="SuffixTextBlockStyle"
       TargetType="{x:Type TextBox}">
    <Setter Property="FontWeight"
            Value="Italic" />
    <Setter Property="Foreground"
            Value="Orange" />
    <Setter Property="Text"
            Value="{Binding Text}" />
    <Setter Property="Margin"
            Value="0 0 3 0" />
</Style>

然后在HierarchicalDataTemplate执行:

<StackPanel Orientation="Horizontal">
    <TextBlock DataContext="{Binding Prefix}"
               Style="{StaticResource PrefixTextBlockStyle} ">  
    ....                              
</StackPanel>

答案 1 :(得分:0)

<StackPanel Orientation="Horizontal">
     <StackPanel.Resources>
         <Style TargetType="TextBlock">
              <Setter Property="Text" Value="{Binding Text}" />
              <Setter Property="FontWeight" Value="{Binding Weight}" />
              <Setter Property="Foreground " Value="{Binding Foreground}" />
              <Setter Property="Margin" Value="0,0,3,0" />
         </Style>
     </StackPanel.Resources>

     <TextBlock DataContext="{Binding PrefixStyle}"/>                                
     <TextBlock DataContext="{Binding ValueStyle}"/>                     
     <TextBlock DataContext="{Binding SuffixStyle}"/> 
      ... 
</StackPanel>

或在app.xaml中使用全局命名样式:

<Application>
    <Application.Resources>
        <Style x:Key="MyTextBlockStyle" TargetType="TextBlock">
            <Setter Property="Text" Value="{Binding Text}" />
            <Setter Property="FontWeight" Value="{Binding Weight}" />
            <Setter Property="Foreground " Value="{Binding Foreground}" />
            <Setter Property="Margin" Value="0,0,3,0" />
        </Style>
    </Application.Resources>
</Application>

其他地方的用法:

<Window>
    <StackPanel>

    <!-- Single textblock with explicit style -->
    <TextBlock DataContext="Blah" Style="{StaticResource MyTextBlockStyle}" />

    <!-- Multiple textblocks with implicit style -->
    <StackPanel Orientation="Horizontal">
        <StackPanel.Resources>
            <Style TargetType="TextBlock" BasedOn={StaticResource MyTextBlockStyle}" />
        </StackPanel.Resources>

        <TextBlock DataContext="{Binding PrefixStyle}"/>                                
        <TextBlock DataContext="{Binding ValueStyle}"/>                     
        <TextBlock DataContext="{Binding SuffixStyle}"/> 
         ... 
    </StackPanel>
</Window>