Accessing elements inside ControlTemplate xaml by c# - wpf

I have a wpf application there i have ControlTemplate in the App.xaml. This ControlTemplate contains Grid and Then Canvas.
<Application.Resources>
<ControlTemplate x:Key="PinTemplate" TargetType="m:Pushpin">
<Grid x:Name="grid2" HorizontalAlignment="left" VerticalAlignment="Center" >
<Canvas x:Name="ContentPopup" Visibility="{TemplateBinding Visibility}">
<StackPanel x:Name="stackPanel1" Canvas.Left="0" Canvas.Top="-20" Visibility="{TemplateBinding Visibility}">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{TemplateBinding Content}"
Margin="0" TextBlock.FontFamily="Segoe UI" TextBlock.FontWeight="Bold" TextBlock.FontSize="10" TextBlock.Foreground="Blue">
</ContentPresenter>
</StackPanel>
</Canvas>
<Canvas>
<Ellipse Name="Ellips12" Fill="AliceBlue" Opacity="0.7" Stroke="Red" StrokeThickness="2" Height="25" Stretch="Fill" Canvas.Top="5" Width="25" />
<TextBlock Text="{TemplateBinding ContentStringFormat }" TextBlock.Foreground="Blue" FontSize="13" TextBlock.TextAlignment="Right" Margin="10,7,10,0">
</TextBlock>
</Canvas>
</Grid>
</ControlTemplate>
</Application.Resources>
I need help to access the Grid and the Canvas inside this ControlTemplate from the mainWindow.xaml.cs.
I want to change the attribut "Visibility" for it when PropertyChanged or when ViewChangeEnd event.
that what i have tried but doesnt work.
ControlTemplate ct = Application.Current.Resources["PinTemplate"] as ControlTemplate;
Grid gr = ct.Resources["grid2"] as Grid;
gr.Visibility = Visibility.Collapsed;
and even this
ControlTemplate ct = Application.Current.Resources["PinTemplate"] as ControlTemplate;
Grid gr = ct.FindName("grid2", this) as Grid;

ControlTemplate.FindName returns the Item only after the template is applied on the control. If you are doing this in UserControl you could get it by overriding OnApplyTemplate. Or if you are outside the UserControl you could use Control.Loaded Event for the same :)
hope it helped :)

Related

How to set the color/background of an Ellipse with a color chosen via a ComboBox?

This is in code behind window
public WpfTestWindow()
{
InitializeComponent();
ComboboxCOLOR.ItemsSource = typeof(Colors).GetProperties();
}
This is the ComboBox
<ComboBox Name="ComboboxCOLOR" Height="25" Width="180">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Rectangle Fill="{Binding Name}" Width="16" Height="16"/>
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
And - whatever color is chosen in ComboBox: It should fill up this Ellipse with that color;
Here below what I got at the moment, it doesnt work...
<Ellipse Fill="{Binding ComboboxCOLOR}" Name="Ellipse"
Margin="5" Height="40" Width="40"
Stroke="Black" StrokeThickness="5">
</Ellipse>
You can refer to the ComboBox using the ElementName in the binding.
Gets or sets the name of the element to use as the binding source object.
If you do not specify the element name, the binding markup extension will interpret ComboboxCOLOR as a property on the current data context of the Ellipse element. Then use the SelectedItem property and the Name property of the item as in your example to bind the Fill
<Ellipse Fill="{Binding SelectedItem.Name, ElementName=ComboboxCOLOR}" Name="Ellipse"
Margin="5" Height="40" Width="40"
Stroke="Black" StrokeThickness="5">
</Ellipse>

WPF Cannot Capture Mouse events in Nested CustomControls

I have the following Control template in my app.xaml: (it is in a template setter in a style, so there is no key)
<ControlTemplate TargetType="{x:Type vm:State}">
<Grid Width="100" Height="60" >
<Border Margin="4"
IsHitTestVisible="{Binding ElementName=Radio_Edit02, Path=IsChecked}"
Padding="4"
BorderBrush="White"
BorderThickness="2"
CornerRadius="5">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{Binding ItemName, RelativeSource={RelativeSource TemplatedParent}}"/>
</Border>
<Grid Margin="3" Background="Transparent">
<local:Anchor Width="6" Height="6" HorizontalAlignment="Center" VerticalAlignment="Top" Background="Red" Visibility="{Binding IsChecked, ElementName=Radio_Edit03, Converter={StaticResource bool2vizibility}}"/>
<local:Anchor Width="6" Height="6" HorizontalAlignment="Right" VerticalAlignment="Center" Background="Red" Visibility="{Binding IsChecked, ElementName=Radio_Edit03, Converter={StaticResource bool2vizibility}}"/>
<local:Anchor Width="6" Height="6" HorizontalAlignment="Left" VerticalAlignment="Center" Background="Red" Visibility="{Binding IsChecked, ElementName=Radio_Edit03, Converter={StaticResource bool2vizibility}}"/>
<local:Anchor Width="6" Height="6" HorizontalAlignment="Center" VerticalAlignment="Bottom" Background="Red" Visibility="{Binding IsChecked, ElementName=Radio_Edit03, Converter={StaticResource bool2vizibility}}"/>
</Grid>
</Grid>
</ControlTemplate>
State derives from thumb
public class State : Thumb, INotifyPropertyChanged
Anchor derives from UserControl
public class Anchor : UserControl, INotifyPropertyChanged
I want to capture a click of the State at one point in the app and of the Anchor in another point of the app.
I want to control when by the two radiobuttons, Radio_Edit02 & Radio_Edit03
when Radio_Edit02 is selected I want to capture the click on the border
when Radio_Edit03 is selected I want to capture the click on the anchor.
I keep getting the click event on the State and cannot get a click on the Anchor.
I tried adding IsHitTestVisible="{Binding ElementName=Radio_Edit03, Path=IsChecked}" to the anchor
but no luck
I tried the following assignement of event handlers in Anchor but neither worked
public Anchor() //constructor
{
//this//this.MouseLeftButtonUp += onAnchorSelect;
//this.PreviewMouseLeftButtonUp += onAnchorSelect;
}
signature for onAnchorSelect is
public void onAnchorSelect(object sender, MouseButtonEventArgs e)
How can I capture a click on the Anchor so that e.Source is the anchor element
thanks

TextBox with image icon in WPF

I want to create TextBox with image in it. This is what I have tried:
<DockPanel Grid.Row="1" Grid.Column="1" Margin="5" >
<Image DockPanel.Dock="Left" Source="D:\my_backup\WPF\SALIENT\SALIENT\Images\d2.PNG" Width="20" Height="20"></Image>
<TextBox Text="test" FontSize="16" HorizontalAlignment="Stretch" Background="Transparent"
</TextBox>
</DockPanel>
this gives me output like this:
but i want the image inside TextBox like this
anyone can help?
You could use this sort of implementation.
you should probably make a user control out of it.
<Border BorderBrush="Black"
BorderThickness="2"
VerticalAlignment="Center"
CornerRadius="5">
<StackPanel Margin="5"
Orientation="Horizontal">
<Image Source="C:\SourceOfTheImage\Path\Image.png"
Height="18"/>
<TextBlock Text="Hello, I am a text block!"
Margin="3 0 0 0"/>
</StackPanel>
</Border>
It looks like this for me
You can set the background property on Textbox, like this (mine is align on right) :
<TextBox x:Name="txtSearch"
Text="Search Item...">
<TextBox.Background>
<ImageBrush ImageSource="Images/Search.png" Stretch="Uniform" AlignmentX="Right">
<ImageBrush.Transform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform X="-3"/>
</TransformGroup>
</ImageBrush.Transform>
</ImageBrush>
</TextBox.Background>
</TextBox>
Set AlignmentX to left if you want to see the image on the left side. Set the TranslateTransform.X to a positive value to add a margin.
Try this:
<Border Padding="5" BorderThickness="2,2,2,2" BorderBrush="Gray" CornerRadius="2,2,2,2">
<DockPanel Grid.Row="1" Grid.Column="1" Margin="5" >
<Image DockPanel.Dock="Left" Source="D:\my_backup\WPF\SALIENT\SALIENT\Images\d2.PNG" Width="20" Height="20"></Image>
<TextBox Text="test" FontSize="16" HorizontalAlignment="Stretch" Background="Transparent" BorderBrush="Transparent" ></TextBox>
</DockPanel>
</Border>
That would be the simplest one-off way of doing it.
You could dump it in a UserControl for reuse.
A second way of achieving this would be to open up the TextBox template and put this icon of yours inside the makeup of the TextBox, which would allow you to avoid needing the DockPanel and Border here, as well as allowing you to make the Template a resource you can easily attach to any Textbox in the future.

DataTemplate only shows Canvas for the last record

I'm using the following DataTemplate
<DataTemplate x:Key="platform_resources">
<StackPanel Orientation="Horizontal">
<Viewbox Width="30" Height="30" ToolTip="Network Domain Count" Stretch="Uniform">
<ContentControl DataContext="{Binding}" Focusable="False" Content="{DynamicResource appbar_server}" />
</Viewbox>
<TextBlock Margin="0,7,0,0" Text="{Binding Path=workload_count}"/>
<Separator Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" />
<Viewbox Width="30" Height="30" ToolTip="Logical Network Count" Stretch="Uniform">
<ContentControl Focusable="False" Content="{DynamicResource appbar_network_server_connecting}" />
</Viewbox>
<TextBlock Margin="0,7,0,0" Text="{Binding Path=vlan_count}"/>
<Separator Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" />
<Viewbox Width="30" Height="30" ToolTip="Network Domain Count" Stretch="Uniform">
<ContentControl Focusable="False" Content="{DynamicResource appbar_network}" />
</Viewbox>
<TextBlock Margin="0,7,0,0" Text="{Binding Path=networkdomain_count}"/>
</StackPanel>
</DataTemplate>
The template displays all the relevant data with separators but only shows the images on the last record. It's leaves spaces where the images are supposed to be, but no images.
Make sure you add x:Shared="False" property to your resources.
Example:
<Canvas x:Key="appbar_server" x:Shared="False">
<!-- ... -->
</Canvas>
This happens because you probably defined some Images (e.g appbar_server) in your resources and trying to display them in multiple items. But Image is a Visual and in WPF each Visual can only have one parent. So when your items are being generated, each item steals the Image from the previous one until the last item finally gets it.
Solution:
Unlike Image, BitmapImage is not a Visual and thus can be set multiple times as the source of different items. So instead of defining Images in your Resources, define BitmapImages:
<Window.Resources>
<BitmapImage x:Key="appbar_server" UriSource="C:\...\appbar_server.png"/>
....
And then instead of ContentControls create Image instances in your DataTemplate to present them:
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Viewbox Width="30" Height="30" ToolTip="Network Domain Count" Stretch="Uniform">
<Image Focusable="False" Source="{DynamicResource appbar_server}" />
</Viewbox>
<TextBlock Margin="0,7,0,0" Text="{Binding Path=workload_count}"/>
...
*Update:
The image is captured in a canvas which seems to be needing some
special wrapper to make this work.
In that case, you should define a DataTemplate for each Canvas like this:
<Window.Resources>
<DataTemplate x:Key="appbar_3d_3ds">
<Canvas Width="76" Height="76" Clip="F1 M 0,0L 76,0L 76,76L 0,76L 0,0">
<Path Width="32" Height="40" Canvas.Left="23" Canvas.Top="18" Stretch="Fill" Fill="Black" Data="F1 M 27,18L 23,26L 33,30L 24,38L 33,46L 23,50L 27,58L 45,58L 55,38L 45,18L 27,18 Z "/>
</Canvas>
</DataTemplate>
....
And then create ContentPresenter Instances in your ItemTemplate with their ContentTemplate set to your pre-defined data templates (e.g. appbar_3d_3ds).
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Viewbox Width="30" Height="30" ToolTip="Network Domain Count" Stretch="Uniform">
<ContentPresenter ContentTemplate="{DynamicResource appbar_3d_3ds}"/>
</Viewbox>
<TextBlock Margin="0,7,0,0" Text="{Binding Path=workload_count}"/>
....

Icon DataTemplate for Icon MenuItem

I create some graphics for menuitem.icon.
<DataTemplate x:Key="navigation_arrow">
<DockPanel LastChildFill="True" HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid>
<Canvas>
<Rectangle Fill="Red" Width="30" Height="20"/>
</Canvas>
</Grid>
</DockPanel>
</DataTemplate>
And then I try use this template for menuitem.icon
<MenuItem Header="" Icon="{Binding navigation_arrow}"/>
But it is empty menuitem. If I insert template code in MenuItem.Icon all work good
First: your binding is wrong. You must use this key as {DynamicResource navigation_arrow} or {StaticResource navigation_arrow}.
But It's not working. Your icon will be "System.Windows.DataTemplate" string, in this case.
DataTemplate means "It will apply a template for a data". You haven't got Data for Icon, so it cannot apply template for this.
You have to add concrete item as icon (like you mentioned) or create a style for it:
<Style TargetType="MenuItem">
<Setter Property="Icon">
<Setter.Value>
<DockPanel LastChildFill="True" HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid>
<Canvas>
<Rectangle Fill="Red" Width="30" Height="20"/>
</Canvas>
</Grid>
</DockPanel>
</Setter.Value>
</Setter>
</Style>
but the fancy way is:
use DrawingBrush from resource
You can use a ContentControl:
<MenuItem.Icon>
<ContentControl ContentTemplate="{StaticResource navigation_arrow}"/>
</MenuItem.Icon>

Resources