标签: controltemplate

在WPF中优雅地覆盖ComboBox的ToggleButton样式

我有一个关于如何优雅地覆盖控件的可视树内的任意元素的问题.我也试图用几种不同的方式解决它,但我遇到了几个问题.通常当我尝试三条不同的路径并且每一路都失败时,我会下楼去喝咖啡,并问一个比我更聪明的人.所以我在这里.

具体细节:

我想要展平组合框的风格,这样它就不会引起人们的注意.我希望它类似于Windows.Forms.ComboBox的FlatStyle我希望它在Windows 7和XP上看起来一样.

主要是,我想改变ComboBox的ToggleButton的外观.

我可以使用Blend并撕掉控件模板的内部并手动更改它们.这对我来说听起来不是很开心.

我尝试使用样式来覆盖ToggleButton的背景,但事实证明整个ComboBox控件实际上是ToggleButton的前端.

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ComboBoxExpiriment2.MainWindow"
x:Name="Window"
xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Classic" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="204" Height="103">
<Grid x:Name="LayoutRoot">
    <ComboBox HorizontalAlignment="Left" Margin="32,26.723,0,0" Width="120" VerticalAlignment="Top" Height="21.277">
    <ComboBox.Style>
      <Style>
        <Setter Property="ToggleButton.Background" Value="Green" />
      </Style>
    </ComboBox.Style>
    </ComboBox>
</Grid>
Run Code Online (Sandbox Code Playgroud)

所以我放弃并使用Blend将其撕掉.我发现它实际上是一个名为ComboBoxTransparentButtonStyle的Style,目标类型为ToggleButton.该样式设置一个ControlTemplate,它使用一个DockPanel,其右侧设置了"Microsoft_Windows_Themes:ClassicBorderDecorator"类型,就是我们实际想要控制的内容.(到目前为止你和我在一起吗?)
这是照片:

例

<Style x:Key="ComboBoxTransparentButtonStyle" TargetType="{x:Type ToggleButton}">
                <Setter Property="MinWidth" Value="0"/>
                <Setter Property="MinHeight" Value="0"/>
                <Setter Property="Width" Value="Auto"/>
                <Setter Property="Height" Value="Auto"/>
                <Setter Property="Background" Value="Transparent"/>
                <Setter Property="BorderBrush" Value="{x:Static Microsoft_Windows_Themes:ClassicBorderDecorator.ClassicBorderBrush}"/>
                <Setter Property="BorderThickness" Value="2"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ToggleButton}">
                            <DockPanel SnapsToDevicePixels="true" Background="{TemplateBinding Background}" LastChildFill="false">
                                <Microsoft_Windows_Themes:ClassicBorderDecorator x:Name="Border" Width="{DynamicResource …
Run Code Online (Sandbox Code Playgroud)

wpf templates combobox styles controltemplate

15
推荐指数
1
解决办法
2万
查看次数

使用控件模板创建图像+文本按钮?

我厌倦了一遍又一遍地创建相同的图像+文本按钮,我想将标记移动到控件模板.这是我的问题:我需要提供模板绑定来将图像和文本添加到模板化按钮,而Button控件似乎没有我可以绑定的属性.

到目前为止,我的模板看起来像这样(对于未知的模板绑定,使用'???'):

<ControlTemplate x:Key="ImageButtonTemplate" TargetType="{x:Type Button}">
    <StackPanel Height="Auto" Orientation="Horizontal">
        <Image Source="{TemplateBinding ???}" Width="24" Height="24" Stretch="Fill"/>
        <TextBlock Text="{TemplateBinding ???}" HorizontalAlignment="Left" Foreground="{DynamicResource TaskButtonTextBrush}" FontWeight="Bold"  Margin="5,0,0,0" VerticalAlignment="Center" FontSize="12" />
    </StackPanel>
</ControlTemplate>
Run Code Online (Sandbox Code Playgroud)

是否可以使用控件模板创建此图像+文本按钮,或者我是否必须转到用户控件才能执行此操作?如果可以使用控件模板完成,我该如何设置模板绑定?

wpf controltemplates controltemplate

15
推荐指数
1
解决办法
2万
查看次数

测量在WPF中在运行时创建的控件

我知道这是一个很受欢迎的问题,但我找不到任何可以回答的问题,但如果我在搜索中遗漏了一些内容,我会道歉.

我正在尝试使用以下代码在运行时创建并测量控件(然​​后测量将用于选框样式滚动控件 - 每个控件的大小不同):

Label lb = new Label();
lb.DataContext= task;
Style style = (Style)FindResource("taskStyle");
lb.Style = style;

cnvMain.Children.Insert(0,lb);

width = lb.RenderSize.Width;
width = lb.ActualWidth;
width = lb.Width;
Run Code Online (Sandbox Code Playgroud)

代码创建一个Label控件并为其应用样式.该样式包含我的控件模板,该模板绑定到对象"任务".当我创建项目时它看起来很完美,但是当我尝试使用上面的任何属性测量控件时,我得到以下结果(我逐步检查并依次检查每个属性):

lb.Width = NaN
lb.RenderSize.Width = 0
lb.ActualWidth = 0
Run Code Online (Sandbox Code Playgroud)

有没有办法获得您在运行时创建的控件的渲染高度和宽度?

更新:

很抱歉取消选择您的解决方案作为答案.他们在我设置的基本示例系统上工作,但似乎没有完整的解决方案.

我觉得它可能与风格有关,所以很抱歉这个烂摊子,但我在这里粘贴整个东西.

一,资源:

    <Storyboard x:Key="mouseOverGlowLeave">
        <DoubleAnimation From="8" To="0" Duration="0:0:1" BeginTime="0:0:2" Storyboard.TargetProperty="GlowSize" Storyboard.TargetName="Glow"/>
    </Storyboard>

    <Storyboard x:Key="mouseOverTextLeave">
        <ColorAnimation From="{StaticResource buttonLitColour}" To="Gray" Duration="0:0:3" Storyboard.TargetProperty="Color" Storyboard.TargetName="ForeColour"/>
    </Storyboard>

    <Color x:Key="buttonLitColour" R="30" G="144" B="255" A="255" />

    <Storyboard x:Key="mouseOverText">
        <ColorAnimation From="Gray" To="{StaticResource buttonLitColour}" Duration="0:0:1" Storyboard.TargetProperty="Color" Storyboard.TargetName="ForeColour"/>
    </Storyboard> …
Run Code Online (Sandbox Code Playgroud)

c# data-binding wpf styles controltemplate

15
推荐指数
2
解决办法
1万
查看次数

WPF - 将UserControl的可见性绑定到属性

我有一个绑定到ObservableCollection的ListView.数据从Internet加载,然后添加到集合中.下载需要几秒钟,我想指示用户数据正在加载.

我创建了一个指示活动的UserControl.我将它放在ControlTemplate中.

<ControlTemplate x:Key="ListViewControlTemplate1" TargetType="{x:Type ListView}">
    <Grid>
        <local:ActivityIndicatorControl 
            HorizontalAlignment="Center" 
            Height="Auto" 
            Margin="0" 
            VerticalAlignment="Center"/>
    </Grid>
</ControlTemplate>
Run Code Online (Sandbox Code Playgroud)

我想将Visibility绑定ActivityIndicatorControl到一个属性,让我们说bool IsLoading并相应地将它设置为Visible/Collapsed.

谢谢!

c# wpf xaml binding controltemplate

15
推荐指数
1
解决办法
3万
查看次数

ContentPresenter.ContentSource与内容

基本上,我不明白这里的真正区别是什么:

TabItem的Microsoft代码使用:

<ContentPresenter ContentSource="Header" ... />
Run Code Online (Sandbox Code Playgroud)

那么,何时使用该Content属性而不是(或除此之外)ContentSource

wpf xaml contentpresenter controltemplate

13
推荐指数
1
解决办法
7568
查看次数

使用ScrollViewer作为模板的一部分进行某些控制时,会处理左键单击

考虑第一版代码(MainWindow.xaml):

<ScrollViewer>
    <local:CustomControl1 Width="1000" Height="1000" Background="Red"/>
</ScrollViewer>
Run Code Online (Sandbox Code Playgroud)

其中CustomControl1派生自ItemsControl.在CustomControl1中,我重写了OnMouseDown事件.这段代码完美无缺,我确实抓住了鼠标按下事件.

现在第二版代码(MainWindow.xaml):

<local:CustomControl1 Width="1000" Height="1000" Background="Red"/>
Run Code Online (Sandbox Code Playgroud)

在Generic.xaml里面,我更改了我的项目控件的模板:

            <ControlTemplate TargetType="{x:Type local:CustomControl1}">
                <Border Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">

                    <ScrollViewer 
                        VerticalScrollBarVisibility="Visible" 
                        HorizontalScrollBarVisibility="Visible"
                        >
                        <ItemsPresenter/>
                    </ScrollViewer>
                </Border>
            </ControlTemplate>
Run Code Online (Sandbox Code Playgroud)

当我将scrollviewer作为控件模板的一部分时,我不再接收OnMouseDownEvent(左键单击).出于某种原因,现在将鼠标按下事件标记为已处理.如果不是重写OnMouseDown,我在items控件构造函数中使用以下语句,则捕获事件:

AddHandler(Mouse.MouseDownEvent, new MouseButtonEventHandler(OnMouseDown), true);
Run Code Online (Sandbox Code Playgroud)

首先,我想了解为什么将scrollviewer放在模板中改变鼠标的行为.第二,有没有人知道一些解决方法?我提出的解决方案(通过捕获处理事件)对我来说是不可接受的.在我的应用程序中,只有当没有任何项控制子项处理它时,我才需要处理鼠标按下事件.

提前致谢.

wpf scrollviewer controltemplate

13
推荐指数
1
解决办法
3035
查看次数

将重点放在ControlTemplate中的控件上(第2部分)

我对那些肯定是最常见的WPF要求之一感到困惑.我已经阅读了这个问题但是我的解决方案的实现不起作用.

这是无视控件的标记:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:local="clr-namespace:WpfTest">
  <Style TargetType="{x:Type local:CustomControl}">
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="{x:Type local:CustomControl}">
          <Border>
            <TextBox x:Name="myTextBox" />
          </Border>
          <ControlTemplate.Triggers>
            <Trigger Property="IsFocused"
                     Value="True">
              <Setter Property="FocusManager.FocusedElement"
                      Value="{Binding ElementName=myTextBox}" />
              <Setter TargetName="myTextBox"
                      Property="Background"
                      Value="Green" />
            </Trigger>
          </ControlTemplate.Triggers>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</ResourceDictionary>
Run Code Online (Sandbox Code Playgroud)

这是包含CustomControl实例的Window的标记:

<Window x:Class="WpfTest.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfTest"
        Title="Window1" Height="300" Width="300">

  <local:CustomControl x:Name="CCtl" />
</Window>
Run Code Online (Sandbox Code Playgroud)

这是代码隐藏的代码:

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
        Loaded += (RoutedEventHandler)delegate { CCtl.Focus(); };
    }
}
Run Code Online (Sandbox Code Playgroud)

加载Window1时,文本框变为绿色(表示触发器有效)但焦点仍然是CCtl而不是文本框.毫无疑问,这与显示以下数据错误的输出有关:

无法找到引用'ElementName = myTextBox'的绑定源.BindingExpression …

wpf xaml focus controltemplate focusmanager

12
推荐指数
1
解决办法
7453
查看次数

在WPF中实现"向下滑动"动画

我正在尝试为Expander控件创建自己的模板.当控件展开时,我希望内容缓慢滑下.

在编译时不知道内容的期望高度.

我以为我们可以将幻灯片定义为动画:

<Storyboard x:Key="ExpandContent">

    <DoubleAnimation 
        Storyboard.TargetName="_expanderContent" 
        Storyboard.TargetProperty="Height" 
        From="0.0" 
        To="{Binding ElementName=_expanderContent,Path=DesiredHeight}"
        Duration="0:0:1.0" />
</Storyboard>
Run Code Online (Sandbox Code Playgroud)

但不幸的是没有.我们收到错误

无法冻结此Storyboard时间轴树以跨线程使用.

看来我们在定义动画参数时不能使用绑定.(也在这个问题中讨论过.)

有没有人对我如何处理这个有任何想法?我担心使用LayoutTransform.ScaleY,因为这会产生扭曲的图像.

这与此问题类似,但这个问题的答案涉及编写代码隐藏,我认为在控件模板中是不可能的.我想知道基于XAML的解决方案是否可以实现.


对于它的价值,这是我的控件模板的当前状态.

<ControlTemplate x:Key="ExpanderControlTemplate"  TargetType="{x:Type Expander}">
    <ControlTemplate.Resources>
            <!-- Here are the storyboards which don't work -->
            <Storyboard x:Key="ExpandContent">

                <DoubleAnimation 
                    Storyboard.TargetName="_expanderContent" 
                    Storyboard.TargetProperty="Height" 
                    From="0.0" 
                    To="{Binding ElementName=_expanderContent,Path=DesiredHeight}"
                    Duration="0:0:1.0" />
            </Storyboard>
            <Storyboard x:Key="ContractContent">

                <DoubleAnimation 
                    Storyboard.TargetName="_expanderContent" 
                    Storyboard.TargetProperty="Height" 
                    From="{Binding ElementName=_expanderContent,Path=DesiredHeight}"
                    To="0.0"
                    Duration="0:0:1.0" />

            </Storyboard>
        </ControlTemplate.Resources>
    <Grid Name="MainGrid" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Name="ContentRow" Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" …
Run Code Online (Sandbox Code Playgroud)

wpf animation controltemplate

12
推荐指数
2
解决办法
2万
查看次数

wpf错误模板 - 在扩展器崩溃时仍然可以看到红色框

我正在对ExpBox中的TextBox的DataSource进行一些验证,并且发现一旦触发了验证错误,如果我折叠了Expander,红色框就会停留在TextBox所在的位置.

<Expander Header="Blah Blah Blah">
  <TextBox Name="TextBox"
           Validation.ErrorTemplate="{DynamicResource TextBoxErrorTemplate}"
           Text="{Binding Path=Blah,
                          UpdateSourceTrigger=PropertyChanged,
                          ValidatesOnDataErrors=True}" />
</Expander>
Run Code Online (Sandbox Code Playgroud)

我试图通过将错误模板的可见性绑定到扩展器来解决这个问题,但是我认为绑定有问题.

<local:NotVisibleConverter x:Key="NotVisibleConverter" />

<ControlTemplate x:Key="TextBoxErrorTemplate">
  <DockPanel>
    <Border BorderBrush="Red" BorderThickness="2" 
            Visibility="{Binding Path=IsExpanded, 
                                 Converter={StaticResource NotVisibleConverter}, 
                                 RelativeSource={RelativeSource AncestorType=Expander}}" >
      <AdornedElementPlaceholder Name="MyAdorner" />
    </Border>
  </DockPanel>
  <ControlTemplate.Triggers>
    <Trigger Property="Validation.HasError" Value="true">
        <Setter Property="ToolTip"
                Value="{Binding RelativeSource={RelativeSource Self}, 
                                Path=(Validation.Errors)[0].ErrorContent}"/>
    </Trigger>
  </ControlTemplate.Triggers>
</ControlTemplate>
Run Code Online (Sandbox Code Playgroud)

我想我的绑定出了问题,有人可以让我回到正轨吗?或者,是否有人知道ErrorTemplate的另一个解决方案仍然可以在Expander崩溃时看到?

validation wpf binding controltemplate

11
推荐指数
1
解决办法
9283
查看次数

如何在ControlTemplate中使用ElementName绑定?

我有多个TextBlocks,它引用了我的应用程序中的不同元素.我的代码在页面中直接使用时工作正常.但是,我想创建一个ControlTemplate和一个ContentControl来减少代码的重复.

如何使用TemplateBinding从ContentControl传递对ElementName的引用到ControlTemplate?以下代码抛出此错误:

"无法将属性'ElementName'中的值转换为'System.String'类型的对象.'System.Windows.TemplateBindingExpression'类型的对象无法转换为'System.String'类型."

除了Tag属性之外,我还尝试了ContentStringFormat,它也没有用.

使用模板使其工作的正确方法是什么?

在此先感谢您的帮助,

---肖恩

这是代码示例:

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
    <Page.Resources>
        <ControlTemplate x:Key="MyTemplate" TargetType="{x:Type ContentControl}">
            <TextBlock Margin="{Binding ElementName={TemplateBinding Tag}, Path=Margin}" Text="{TemplateBinding Content}" TextAlignment="{Binding ElementName={TemplateBinding Tag}, Path=TextAlignment}" Width="{Binding ElementName={TemplateBinding Tag}, Path=Width}" />
        </ControlTemplate>
    </Page.Resources>
    <StackPanel>
        <TextBlock x:Name="AnotherElement" Margin="10" Text="Main TextBlock" TextAlignment="Center" Width="100" />
        <TextBlock x:Name="AnotherElement2" Margin="20" Text="Second TextBlock" TextAlignment="Left" Width="250" />
        <TextBlock Margin="{Binding ElementName=AnotherElement, Path=Margin}" Text="Here is my TextBlock!" TextAlignment="{Binding ElementName=AnotherElement, Path=TextAlignment}" TextTrimming="CharacterEllipsis" Width="{Binding ElementName=AnotherElement, Path=Width}" />
        <TextBlock Margin="{Binding ElementName=AnotherElement2, Path=Margin}" Text="Here is my Second TextBlock!" TextAlignment="{Binding ElementName=AnotherElement2, …
Run Code Online (Sandbox Code Playgroud)

wpf xaml binding controltemplate

11
推荐指数
1
解决办法
6万
查看次数