I am trying to write a custom control in Windows UWP by inheriting from a Control class (A button with custom action). On clicking of this button I want to show a panel at the bottom of the page irrespective of where the control is being used in the page (Kind of a popup but I need the freedom in defining the position of the panel on the screen).
Can anyone help how i can get this done in XAML. Below is the template I am using for my custom control.
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UI.Controls"
xmlns:converters="using:UI.ValueConverters">
<Style TargetType="local:Plugin">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:Plugin">
<Grid>
<Grid.Resources>
<converters:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
<x:Double x:Key="EllipseDimension">30</x:Double>
</Grid.Resources>
<Button Name="PluginButton"
Width="{TemplateBinding PluginWidth}"
Height="{TemplateBinding PluginHeight}"
Command="{Binding PluginTrigger}"
Padding="0"
VerticalAlignment="Top"
AutomationProperties.Name="Main button"
Background="Transparent"
BorderThickness="0"
TabIndex="0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="48" />
</Grid.ColumnDefinitions>
<SymbolIcon Symbol="{TemplateBinding Symbol}"
Visibility="{Binding Image, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=true}"
Foreground="Black"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ToolTipService.ToolTip="{TemplateBinding Label}" />
<Ellipse Visibility="{Binding Image, Converter={StaticResource NullToVisibilityConverter}}"
Width="{StaticResource EllipseDimension}"
Height="{StaticResource EllipseDimension}">
<Ellipse.Fill>
<ImageBrush ImageSource="{Binding Image}" />
</Ellipse.Fill>
</Ellipse>
</Grid>
</Button>
<StackPanel Name="popuptoshow"></StackPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Related
I'm trying to make a simple WPF app that has sections that fill the available width. Despite trying various ways of stretching the width of elements, containers, and children, nothing is working and I can't figure out why.
Another question said to use uniformgrid which worked well EXCEPT that it set the height of all the elements uniformly which was definitely not what I wanted. I want all of the sections to look like the one in the picture - filled width, height auto based on the content. Here's the basic setup:
<Window x:Class="A_Customizer.MainWindow"
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"
xmlns:local="clr-namespace:A_Customizer"
mc:Ignorable="d"
Title="MainWindow"
Background="#FF2B2B2B"
Width="800"
>
<Window.Resources>
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Cursor" Value="Hand"/>
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type CheckBox}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Cursor" Value="Hand"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid Name="mainApp" >
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<WrapPanel Grid.Row="0" >
<Button ToolTip="Click to apply the below settings to this Jumpbox" Click="ApplyCustomizations">Customize</Button>
</WrapPanel>
<ScrollViewer Grid.Row="1">
<WrapPanel HorizontalAlignment="Stretch" >
<GroupBox
Background="#FFE2E2E2"
BorderBrush="#FF7F7F7F"
Margin="10,10,10,10"
Name="pathsBox"
HorizontalContentAlignment="Stretch"
HorizontalAlignment="Stretch"
>
<GroupBox.Header>
<Border Background="#FFAFAFAF" CornerRadius="3">
<Label FontWeight="Bold">Key Paths</Label>
</Border>
</GroupBox.Header>
<StackPanel HorizontalAlignment="Stretch">
<Grid Margin="0,10,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="50"/>
</Grid.ColumnDefinitions>
<TextBox Name="homeFolder" Grid.Column="0" HorizontalAlignment="Stretch"></TextBox>
<Button Grid.Column="1" Click="NewQuickPath" ToolTip="Change home folder">
<Image Source="images\add_folder.png" Height="25" Cursor="Hand"></Image>
</Button>
</Grid>
<TextBox Name="progFolder" Grid.Column="0" HorizontalAlignment="Stretch"></TextBox>
</StackPanel>
</GroupBox>
<GroupBox
Background="#FFE2E2E2"
BorderBrush="#FF7F7F7F"
Margin="10,10,10,10"
Name="quickBox"
Height="auto"
HorizontalContentAlignment="Stretch"
>
<GroupBox.Header>
<Border Background="#FFAFAFAF" CornerRadius="3">
<Label FontWeight="Bold">Quick Access Folders</Label>
</Border>
</GroupBox.Header>
<StackPanel HorizontalAlignment="Stretch">
<TextBlock TextWrapping="Wrap" Margin="15">
There are going to be folders you'll need to access frequently and keeping them pinned on top of the left menu in Explorer is helpful.
Select here to add them to the list of folders restored with the "Customize" button. Click any folder to remove it.
</TextBlock>
<Border CornerRadius="3" Background="#FFF3C7C7" Margin="6" Visibility="Collapsed" Name="quickErr" Tag="err_box">
<TextBlock Tag="errMsg" Foreground="#FFFD3434" TextWrapping="Wrap" Margin="6" ></TextBlock>
</Border>
<UniformGrid Name="quickPathsArea" Columns="1">
</UniformGrid>
<Grid Margin="0,10,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="50"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" HorizontalAlignment="Stretch"></TextBox>
<Button Grid.Column="1" Click="NewQuickPath" ToolTip="Add a new folder">
<Image Source="images\add_folder.png" Height="25" Cursor="Hand"></Image>
</Button>
</Grid>
</StackPanel>
</GroupBox>
</wrappanel>
</scrollviewer>
</grid>
StackPanel with Orientation="Vertical" (default value) instead of WrapPanel should work: it will allow each child element use full width and as much height as necessary
I am trying to make a style for some buttons, at first I made one style for the buttons but then I needed an icon in them so i put the icon in the style.
However that is not the way to go, I can't get the icon in the button but out of the style.
code in style:
<Style x:Name="stlBtnOpen" x:Key="stlBtnOpen" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="borderBtnOpen" CornerRadius="10" BorderBrush="DarkGray" BorderThickness="1" Background="Transparent">
<Grid Background="{DynamicResource AccentColorBrush}" Margin="6">
<Grid.OpacityMask>
<VisualBrush Stretch="Fill" Visual="{DynamicResource appbar_folder}"/>
</Grid.OpacityMask>
</Grid>
</Border>
<ControlTemplate.Triggers>
//some events
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
code in element:
<Button Grid.Column="2" x:Name="btnOpen" Click="btnOpen_Click">
<Border x:Name="borderBtnOpen" CornerRadius="10" BorderBrush="DarkGray" BorderThickness="1" Background="Transparent">
<Grid Background="{DynamicResource AccentColorBrush}" Margin="6">
<Grid.OpacityMask>
<VisualBrush Stretch="Fill" Visual="{DynamicResource appbar_folder}"/>
</Grid.OpacityMask>
</Grid>
</Border>
</Button>
*Did you try to put the image in the grid you put in you button's content :
<Button Grid.Column="2" x:Name="btnOpen" Click="btnOpen_Click">
<Border x:Name="borderBtnOpen" CornerRadius="10" BorderBrush="DarkGray" BorderThickness="1" Background="Transparent">
<Grid Background="{DynamicResource AccentColorBrush}" Margin="6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="0">
<Rectangle.Fill>
<VisualBrush Stretch="Fill" Visual="{DynamicResource appbar_folder}"/>
</Rectangle.Fill>
</Rectangle>
<Textblock Grid.Column="1"/>
</Grid>
</Border>
</Button>
Got that from memory, but it shouldn't be too far from what you need (you might also replace the grid with a stackpanel that would reduce the boilerplate from the columns definitions)
Ah and don't forget to put something into the textblock if you want to have something in your button :)
EDIT :
Well this IS working for me, but there are a coupe of issues inherent to using a brush to fill another object.
But first here is the EXACT working markup
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Width="525"
Height="350">
<Grid>
<Button x:Name="btnOpen"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Click="">
<Border x:Name="borderBtnOpen"
Background="Transparent"
BorderBrush="DarkGray"
BorderThickness="1"
CornerRadius="10">
<Grid Margin="6"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="{DynamicResource AccentColorBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="0" Width="20px">
<Rectangle.Fill>
<SolidColorBrush Color="Blue"/>
</Rectangle.Fill>
</Rectangle>
<TextBlock Grid.Column="1" Text="bonjour"/>
</Grid>
</Border>
</Button>
</Grid>
</Window>
There are 2 issues here :
The Border will not extend itself to the button size (you can see it if you force a larger width than what the button really needs)
You will have to manually define the rectangle's size (the brush only fill and does not define it's size) or else, you will have a rectangle with a 0px size which is effectively non existent on screen
For the border issue, you might want to check out what the OP of this question did (linking here because the related documentation is also inked)
EDIT2
Changed the above code so that the rectangle can be visible when the Border is large enough (you can still refer to the linked question for the border issue)
I am trying to make a reuseable button that has a Text followed by an X button (kind of like the close tab button on Google Chrome). I figured to do it something like this;
<Style x:Key="TestButtonStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Margin ="3,5,3,5" BorderBrush="Black" Grid.Column="0" />
<Button Background="White" BorderBrush="White" Content="X" Grid.Column="1" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Button Style="{StaticResource TestButtonStyle}" Content="Testing" Padding="5" Margin="5" />
The problem with this is that Button Click command works for the Label as well as the X Button. If I put the click command into the Style then every button will have the same click command. What is the best way to accomplish this?
You can do TemplateBinding on button to inherit Command from parent template button.
<Button Background="White" BorderBrush="White" Content="X"
Grid.Column="1" Command="{TemplateBinding Command}" />
This way you can set different commands on multiple buttons and re-use the same style:
<Button Style="{StaticResource TestButtonStyle}" Content="Testing"
Padding="5" Margin="5" Command="{Binding TestCommand}"/>
I have a number of buttons on a form (devcomponents ButtonDropDown controls to be precise).
I want to show a tool tip for each that contains a header at the top, an image on the left and a description on the right.
The header needs to be tied to the ButtonDropDown.Header, the image to the ButtonDropDown.Image. I also then need to define the description somewhere.
I've only been using WPF for a few weeks so I've not managed to find any answers via searching, though I have studied a few.
Below is my attempt at creating a template that really doesn't work at all:
<Style TargetType="dcr:ButtonDropDown">
<Setter Property="OverridesDefaultStyle" Value="True"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="dcr:ButtonDropDown">
<ContentControl>
<ContentControl.ToolTip>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"
Content="{TemplateBinding Header}" FontWeight="Bold" />
<Viewbox Grid.Row="1" Grid.Column="0" Width="64" Height="32" Margin="3">
<ContentControl Content="{TemplateBinding Image}" />
</Viewbox>
<Label Grid.Row="1" Grid.Column="1"
Content="{TemplateBinding ToolTip.Content}" />
</Grid>
</ContentControl.ToolTip>
</ContentControl>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I then define a button as follows:
<dcr:ButtonDropDown Header="-X" Command="{Binding MoveCommand}" CommandParameter="xMinus"
ImagePosition="Top" IsEnabled="{Binding UserConfiguration.Move.Visible}"
ToolTip="move x axis down">
<dcr:ButtonDropDown.Image>
<Viewbox Width="32" Height="32" Margin="3">
<ContentControl Content="{StaticResource minusXImage}" />
</Viewbox>
</dcr:ButtonDropDown.Image>
</dcr:ButtonDropDown>
Please could someone give me an idea how to go about this?
I've gone some way to answering this question.
The following style is defined for ToolTip:
<Style TargetType="ToolTip">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<Border Background="GhostWhite" BorderBrush="Gainsboro" BorderThickness="1">
<Grid Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"
Content="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ToolTip}},
Path=PlacementTarget.(dcr:ButtonDropDown.Header)}"
FontWeight="Bold" />
<Viewbox Grid.Row="1" Grid.Column="0" Width="64" Height="32" Margin="3">
<ContentControl Content="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ToolTip}},
Path=PlacementTarget.(dcr:ButtonDropDown.Image)}" />
</Viewbox>
<Label Grid.Row="1" Grid.Column="1"
Content="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ToolTip}},
Path=PlacementTarget.(dcr:ButtonDropDown.ToolTip)}" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I then define a button as above and the ToolTip text and header appear in the ToolTipas required.
The key is the binding:
Content="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ToolTip}},
Path=PlacementTarget.(dcr:ButtonDropDown.Header)}"
Which finds the Tooltip as an ancestor of Label and casts its PlacementTarget into a ButtonDropDown
What doesn't work is the image. This appears in the ToolTip but is removed from the button.
This will also break any other controls' tooltips if they are not ButtonDropDown controls.
I'm beginning to think I'll need to create some custom controls that contain the information I require for the ToolTip for each control.
<UserControl.Resources>
<Style x:Key="PushPinStyle" TargetType="Maps:Pushpin">
<Setter Property="Width" Value="250"/>
<Setter Property="Height" Value="80"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Foreground="Red" Text="HERE MUST BE TEXT" Grid.Row="0"/>
<Image Grid.Row="1" Source="ms-appx:///Images/Icons/Pushpin.png" Stretch="Uniform" HorizontalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
When i create pushpin:
Pushpin pushpin = new Pushpin();
pushpin.Style = this.Resources["PushPinStyle"] as Style;
I want to access the text block's text and visibility properties from C# code.
There will be something like a button "Go to next pushpin" on a page, the map gets centred on other pushpin, and TextBlock is becoming visible
Xyroid's comment helped me out:
<TextBlock Foreground="Red" HorizontalAlignment="Center" Visibility="{Binding Path=Visibility}" Text="{Binding Path=Label}" Grid.Row="0"/>
<Image Grid.Row="1" Source="ms-appx:///Images/Icons/Pushpin.png" Stretch="Uniform" HorizontalAlignment="Center"/>