I have a custom control containing a path that has a templated tooltip. I want to be able to get a reference to a grid in the template at runtime so that I can modify it's children depending on use.
I thought I could use GetTemplateChild to get a reference to the grid in the template from within the OnApplyTemplate method of the control but this method is not firing.
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
_tooltipDetails = (Grid)GetTemplateChild("TooltipDetailsGrid");
}
How else might I be able to do this?
Here is the user control's XAML.
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" x:Class="MiX.AssetManagement.UI.Timeline.Silverlight.TimelineBarRibbonItem"
FontSize="9.333" Foreground="White" mc:Ignorable="d">
<UserControl.Resources>
<ControlTemplate x:Key="ToolTipControlTemplateTimelineView" TargetType="ToolTip">
<StackPanel Orientation="Horizontal" Margin="16,0,0,0">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="OpenStates">
<VisualState x:Name="Closed"/>
<VisualState x:Name="Open"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border CornerRadius="4">
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#7F000000" Offset="0"/>
<GradientStop Color="#B2000000" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
<Grid Margin="4">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Border x:Name="Info" Height="16" Width="16" BorderThickness="2" CornerRadius="8" HorizontalAlignment="Left" VerticalAlignment="Top">
<Border.BorderBrush>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="White" Offset="0"/>
<GradientStop Color="#7FFFFFFF" Offset="1"/>
</LinearGradientBrush>
</Border.BorderBrush>
<Path Fill="White" Stretch="Fill" Margin="5.229,2.089,5.035,2.82" RenderTransformOrigin="0.5,0.5" UseLayoutRounding="False" Data="M0.77471197,5.0623446 L2.4198356,5.0623446 L2.4198356,10.18 L0.77471197,10.18 z M0.72914064,3.0891075 L2.4654069,3.0891075 L2.4654069,4.3332038 L0.72914064,4.3332038 z">
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Path.RenderTransform>
</Path>
</Border>
<ContentPresenter d:LayoutOverrides="Width, Height" Margin="20,0,0,0"/>
<Grid Grid.Column="1" x:Name="TooltipDetailsGrid">
<TextBlock Text="Tooltip in a Grid"/>
</Grid>
</Grid>
</Border>
</StackPanel>
</ControlTemplate>
</UserControl.Resources>
<Path x:Name="RibbonItem" Cursor="Hand">
<Path.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF66CC33"/>
<GradientStop Color="#FF339900" Offset="1"/>
</LinearGradientBrush>
</Path.Fill>
<ToolTipService.ToolTip>
<ToolTip x:Name="RibbonItemTooltip" Content="" Foreground="#FFFFFFFF" FontSize="9.333" Placement="Mouse" Template="{StaticResource ToolTipControlTemplateTimelineView}"/>
</ToolTipService.ToolTip>
<Path.Data>
<GeometryGroup x:Name="RibbonItemGeometryGroup">
<RectangleGeometry x:Name="RibbonItemBackground" />
</GeometryGroup>
</Path.Data>
</Path>
</UserControl>
You need to be handling code in the ToolTip Classes OnApplyTemplate method. Here is my untested stab at what you need to do:-
Inherit from ToolTip and override the OnApplyTemplate method in this new class:-
public MyToolTip : ToolTip
{
public override void OnApplyTemplate()
{
//Perhaps to stuff
base.OnApplyTemplate();
//Perhaps to other stuff
}
}
In your resources you now set the TargetType to local:MyToolTip and ensure your assembly namespace is placed with the local alias in the user control element.
Now in your Xaml:-
<ToolTipService.ToolTip>
<local:MyToolTip x:Name="RibbonItemTooltip" Content="" Foreground="#FFFFFFFF" FontSize="9.333" Placement="Mouse" Template="{StaticResource ToolTipControlTemplateTimelineView}"/>
</ToolTipService.ToolTip>
I have resolved this in a slightly different way. Rather than modify the template at runtime I have created an instance of the template for each use case. I can then apply the correct template when I create the instance and elements in the template bind to control class to populate the tooltip with the appropriate values.
This is probably a better approach as the structure of the tooltips is now clearly visible in the XAML, rather than being hidden away in the code.
Related
I'm already desperate to find the answer why this happens... here's my code:
ResourceDictionary
<Color x:Key="ControlStrokeColorDefault">#0F000000</Color>
<Color x:Key="ControlStrokeColorSecondary">#29000000</Color>
<LinearGradientBrush x:Key="ControlElevationBorderBrush" MappingMode="Absolute" StartPoint="0,0" EndPoint="0,3">
<LinearGradientBrush.RelativeTransform>
<ScaleTransform CenterY="0.5" ScaleY="-1" />
</LinearGradientBrush.RelativeTransform>
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.33" Color="{DynamicResource ControlStrokeColorSecondary}" />
<GradientStop Offset="1.0" Color="{DynamicResource ControlStrokeColorDefault}" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
Panel
<Grid Background="#29000000">
<WrapPanel Background="#F7F7F7" VerticalAlignment="Center" HorizontalAlignment="Center">
<Border Margin="20" Width="100" Height="60" BorderThickness="2" BorderBrush="{DynamicResource ControlElevationBorderBrush}">
<TextBlock>Ok</TextBlock>
</Border>
<Border Margin="20" Width="100" Height="100" BorderThickness="2" BorderBrush="{DynamicResource ControlElevationBorderBrush}">
<TextBlock>???</TextBlock>
</Border>
</WrapPanel>
</Grid>
As a Result, I get that the gradient is calculated only on the first element... is this a wpf bug or am I missing something?
this is because of ScaleY="-1" in ScaleTransform
Scale creates different sizes at different heights
I have created a ControlTemplate for a TextBox that includes a label for it. However, When I try to use Tab to navigate the controls I have to press tab twice to enter the textbox field, as if it's focusing on another element inside. I tried messing the labels focusability and what not but that doesn't seem to be the issue. Here is the code:
<ControlTemplate x:Key="custTextbox" TargetType="{x:Type TextBox}">
<Canvas x:Name="customTextbox">
<Border CornerRadius="3, 0, 0 ,3" BorderThickness="1, 1, 0, 1"
Height="30" x:Name="brdTextboxLabel" Width="98">
<Border.BorderBrush>
<LinearGradientBrush StartPoint=".5,0" EndPoint=".5,1">
<GradientStop Color="#3C3F48" Offset=".88"/>
<GradientStop Color="#9CA1A8" Offset=".96"/>
</LinearGradientBrush>
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush StartPoint=".5, 0" EndPoint=".5, 1">
<GradientStop Color="#414447" Offset="0"/>
<GradientStop Color="#4E525B" Offset=".08"/>
</LinearGradientBrush>
</Border.Background>
<Canvas>
<Rectangle Height="24" x:Name="rectangle3" Stroke="#636369"
Width="1" Canvas.Left="96" Canvas.Top="2" />
<Label Canvas.Left="0" Padding="9,6.5,0,0" Foreground="#BABBBF"
FontWeight="Bold" Canvas.Top="0" FontSize="11"
Content="{TemplateBinding Tag}" Height="28"
x:Name="lblTextboxHeader" Width="92" />
</Canvas>
</Border>
<!-- ========================================= -->
<Border CornerRadius="0,3,3,0" BorderThickness="0,1,1,1" Canvas.Left="98"
Height="30" x:Name="brdTextbox" Width="348">
<Border.BorderBrush>
<LinearGradientBrush StartPoint=".5,0" EndPoint=".5,1">
<GradientStop Color="#3C3F48" Offset=".88"/>
<GradientStop Color="#9CA1A8" Offset=".96"/>
</LinearGradientBrush>
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush StartPoint=".5, 0" EndPoint=".5, 1">
<GradientStop Color="#414447" Offset="0"/>
<GradientStop Color="#4E525B" Offset=".08"/>
</LinearGradientBrush>
</Border.Background>
<Canvas>
<TextBox TabIndex="0" Background="Transparent" CaretBrush="#8C8CA1"
FontSize="16" Padding="4, 3, 0 ,0" BorderBrush="Transparent"
Foreground="#D4D5DA" Canvas.Left="0" Canvas.Top="-1"
Height="30" x:Name="textBox1" Width="347"/>
</Canvas>
</Border>
</Canvas>
</ControlTemplate>
Sorry if it's a mess of a ControlTemplate, it was the first I had ever made when starting wpf/xaml.
Thank you for your time!
HA! Figured it out while solving an issue on another control.
The problem was I, essentially, had 2 TextBoxes each time I used the template.
a simple map would be:
<TextBox>
<ControlTemplate>
<Label/>
<Textbox/>
</ControlTemplate>
</TextBox>
So I just had to make the control I put in the window have KeyboardNavigation.IsTabStop="false" So it would pass that textbox and go to the one inside my ControlTemplate.
I have a grid, which contains a Canvas and StackPanel on same level. I mean the StackPanel placed on the top of the canvas. The canvas contains multiple elements which should be dragable. And I have to handle the Drop event of the StackPanel. The drop event not working if the stackpanel does not contain any child elements, even if I set the height for stackpanel. If I set the Background property for StackPanel it will work, but in this case the mousemove events of canvas child elements(below stackpanel) not working.
Here is the XAML
<Grid>
<jas:DragCanvas
x:Name="dragCanvas"
Grid.Row="1"
AllowDragging="{Binding ElementName=btnAllowDragging, Path=IsChecked}"
AllowDragOutOfView="{Binding ElementName=btnAllowDragOutOfView, Path=IsChecked}"
>
<Ellipse
Canvas.Left="100" Canvas.Bottom="100"
Width="65" Height="70">
<Ellipse.Fill>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<LinearGradientBrush.GradientStops>
<GradientStop Color="LightGray" Offset="0" />
<GradientStop Color="Black" Offset="0.75" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Ellipse.Fill>
</Ellipse>
</jas:DragCanvas>
<DockPanel LastChildFill="False">
<Border DockPanel.Dock="Left" BorderBrush="Black" BorderThickness="2">
<StackPanel x:Name="stackPanel" Drop="StackPanel_Drop" AllowDrop="True">
<Border Height="100" Width="100" Background="Red"></Border>
</StackPanel>
</Border>
</DockPanel>
</Grid>
I have developed a custom data grid control. This control has two parts, one is the custom template used by the data grid itself and the other is my custom control which adds a title area to the data grid.
I have a class called CustomDataGrid, here is the XAML.
<UserControl x:Class="MDT_Designer.Presentation.ScreenControls.CustomDataGrid"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
Name="CDataGrid" >
<UserControl.Resources>
<ResourceDictionary x:Key="Dictionary" Source="CustomizedControls.xaml"/>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="{Binding ElementName=CDataGrid, Path=TitleAreaHeight}"/>
<RowDefinition Height="{Binding ElementName=CDataGrid, Path=GridAreaHeight}"/>
</Grid.RowDefinitions>
<Grid Name="TitleArea" DockPanel.Dock="Top" Background="{Binding ElementName=CDataGrid, Path=TitleBackColor}" >
<Viewbox HorizontalAlignment="{Binding ElementName=CDataGrid, Path=TitleAlignment}">
<TextBlock Name="TitleText" Text="{Binding ElementName=CDataGrid, Path=Title}" Margin="2,0,0,0" FontFamily="{Binding ElementName=CDataGrid, Path=TitleFontFamily}" Foreground="{Binding ElementName=CDataGrid, Path=TitleTextColor}"/>
</Viewbox>
</Grid>
<DataGrid Name="DataGridArea" Grid.Row="1" IsReadOnly="True" HorizontalGridLinesBrush="DarkGray" VerticalGridLinesBrush="DarkGray" VerticalScrollBarVisibility="Visible" Background="AliceBlue" >
</DataGrid>
</Grid>
</UserControl>
In my CustomDataGrid.xaml.cs file I have defined properties as such.
public static DependencyProperty TitleAlignmentProperty = DependencyProperty.Register("TitleAlignment", typeof(HorizontalAlignment), typeof(CustomDataGrid));
public HorizontalAlignment TitleAlignment
{
get { return (HorizontalAlignment)base.GetValue(TitleAlignmentProperty); }
set { base.SetValue(TitleAlignmentProperty, value); }
}
I am just showing one as a sample, and this works. I do wish that I could change the binding in the XAML to get rid of ElementName=CDataGrid, but any way I have as an alternative doesn't work.
Now to my problem. My custom template for the data grid control itself is stored in the dictionary CustomizedControls.xaml.
Here is one example of binding issues. I had to create this resource.
<LinearGradientBrush x:Key="HeaderBackgroundBrush" EndPoint="0.5,1" StartPoint="0.5,0" >
<GradientStop Color="{DynamicResource {x:Static SystemColors.ControlLightColorKey}}" Offset="0" />
<GradientStop Color="{DynamicResource {x:Static SystemColors.ControlDarkColorKey}}" Offset="1" />
</LinearGradientBrush>
Then I use it in Border definition for the column header.
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
<Grid>
<Border x:Name="columnHeaderBorder" BorderThickness="1" Padding="3,0,3,0"
Background="{DynamicResource HeaderBackgroundBrush}">
<Border.BorderBrush>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="{DynamicResource BorderLightColor}" Offset="0" />
<GradientStop Color="{DynamicResource BorderDarkColor}" Offset="1" />
</LinearGradientBrush>
</Border.BorderBrush>
<ContentPresenter x:Name="columnHeaderPresenter" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Style="{DynamicResource HeaderContentStyle}" />
</Border>
<Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left" Style="{StaticResource ColumnHeaderGripperStyle}" />
<Thumb x:Name="PART_RightHeaderGripper" HorizontalAlignment="Right" Style="{StaticResource ColumnHeaderGripperStyle}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Then to change it in my code behind I have to do this.
LinearGradientBrush headerBrush = (LinearGradientBrush)TryFindResource("HeaderBackgroundBrush");
headerBrush.GradientStops[0] = new GradientStop(brush.Color, 0.0);
I cannot change the brush itself, I can just change a property of the brush. I have tried every binding technique I can think of, but nothing seems to work when the style is in a dictionary.
What I would like to be able to do is somehow bind something like BorderLightColor, which is BorderBrush setting, so that in my code behind I can change it's value.
Any help would make my day, it would make my whole weekend in fact. Thanks.
Why cant you change the brush? You should be able to just assign the brush reference to the control. Does this not work? FindResource should search the Parent Element of the FrameworkElement you are calling it on and up the tree, the application resources, then Themes ending in System Resources. Forgive my VB...
Private Sub Button_Click(ByVal sender as Object, ByVal e as System.Windows.RoutedEventArgs)
Dim MyBrush2 as Brush = Me.FindResource("Brush2")
Me.MyRect.Background = MyBrush2
End Sub
And the window contents:
<Window.Resources>
<LinearGradientBrush x:Key="Brush1" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
<LinearGradientBrush x:Key="Brush2" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF0800FF" Offset="0"/>
<GradientStop Color="Red" Offset="1"/>
</LinearGradientBrush>
</Window.Resources>
<Grid x:Name="LayoutRoot">
<Grid x:Name="MyRect" HorizontalAlignment="Left" Margin="63,66,0,174" Width="242" Background="{DynamicResource Brush1}" />
<Button Content="Button" HorizontalAlignment="Right" Height="60" Margin="0,117,95,0" VerticalAlignment="Top" Width="156" Click="Button_Click"/>
</Grid>
Im trying to create a stackpanel with a rounded background, that also has a linearbrush from grey to trasparent
I used the ideas exposed here to prevent clipping
http://chriscavanagh.wordpress.com/2008/10/03/wpf-easy-rounded-corners-for-anything/
The problem now is that the text inside the stackpanel also has degradation and then turns invisible
any help?
Similar question
How do I create a WPF Rounded Corner container?
Code:
<Border Margin="235,78,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"
BorderBrush="Red" BorderThickness="1" CornerRadius="8" >
<Grid>
<Border Name="mask" CornerRadius="7">
<Border.Background>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<GradientStop Color="Gray" Offset="0"/>
<GradientStop Color="Transparent" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
</Border>
<StackPanel Orientation="Horizontal" >
<StackPanel.OpacityMask>
<VisualBrush Visual="{Binding ElementName=mask}"/>
</StackPanel.OpacityMask>
<Image Height="16" Width="16" RenderOptions.BitmapScalingMode="NearestNeighbor" />
<TextBlock Foreground="Black" Margin="5,0,3,0" Text="00620"/>
<TextBlock Foreground="Black" Margin="5,0,3,0" Text="Error sincronización" />
</StackPanel>
</Grid>
</Border>
This is due to the OpacityMask, try to remove these lines from your XAML:
<StackPanel.OpacityMask>
<VisualBrush Visual="{Binding ElementName=mask}"/>
</StackPanel.OpacityMask>
And it should work