Reuseable help Button and help popup - wpf

I have about 30 views and corresponding VMs in my application. I have a HelpButton next to most user controls which gives some description of what the field is for. When the user clicks on that Button, a Popup opens and gives the description. What will be the best way to make this functionality reusable in all the views?
I have created a ControlTemplate for the HelpButton and the help Popup but can I go further than this? Thanks.
<Style x:Key="HelpButton" TargetType="{x:Type Button}" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Ellipse Focusable="True" Height="16" Width="16">
<Ellipse.Fill>
<ImageBrush ImageSource="../../Resources/Icons/Help.png" />
</Ellipse.Fill>
</Ellipse>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

I see that it's been a while since this question was asked, but I figured I would reply in case someone else comes across this problem and is looking for a solution.
Put it in a ResourceDictionary in a separate Resources.xaml that is accessible from all of your other views:
<ResourceDictionary xmlns...>
<Style x:Key="HelpButton" TargetType="{x:Type Button}" >
...
</Style>
</ResourceDictionary>
Then use it from your Resources section (as you no doubt did before) in your xaml like this:
<UserControl xmlns...>
<UserControl.Resources>
<ResourceDictionary Source="Resources.xaml"/>
</UserControl.Resources>
<Button Style="{StaticResource HelpButton}" />
</UserControl>

Related

Create a visual template for grid

I am trying to create a visual template (saved in resource dictionary as xaml code) for a grid object, that I will apply to various grid objects created later in runtime.
I need a simple style with border and background.
What would be the best way of doing this?
Simple working examples would be greatly appreciated.
Ok, so, after searching for examples, I tried something like this:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="TestStyle">
<Setter Property="Background" Value="#FF873507" />
<Setter.Value>
<ControlTemplate>
<Grid>
<Border BorderThickness="7" CornerRadius="4">
<Border.BorderBrush>
<SolidColorBrush Color="#73B2F5"/>
</Border.BorderBrush>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Style>
</ResourceDictionary>
WPF doesn't really work like that... because the Grid class has no Template property, you cannot define a new ControlTemplate for it. The nearest thing that you can do is to create a UserControl with the UI elements that you want to use and then display the UserControl wherever you want to display those controls.
Alternatively, you could define your content inside a ControlTemplate if the inner controls will always be the same:
<ControlTemplate x:Key="StaticGrid">
<Grid>
<Border BorderThickness="7" CornerRadius="4">
<Border.BorderBrush>
<SolidColorBrush Color="#73B2F5"/>
</Border.BorderBrush>
<!--Add your inner elements here-->
</Border>
</Grid>
</ControlTemplate>
You could then display it like this:
<ContentControl Template="{StaticResource StaticGrid}" />
However, you wouldn't be able to add different inner elements using this method. If you used the UserControl method, you could potentially replace the word UserControl with Grid so that you were in fact extending the Grid class, but you still wouldn't be able to add different elements to it.
The best that you could do in a Style would be to set the Background property.
After more tries and frustrations, I found a much simpler solution, that worked for me.
Instead of trying to apply the style to the grid, I applied it to the border around the grid.
So, my dictionary looks like this:
<Style x:Key="TestStyle" TargetType="{x:Type Border}">
<Setter Property="Background" Value="#FFBDACA2" />
<Setter Property="BorderBrush" Value="#FFFF5E00" />
<Setter Property="CornerRadius" Value="30,30,30,30" />
<Setter Property="BorderThickness" Value="10" />
</Style>
And my main frame xaml:
<Border Style="{StaticResource TestStyle}" >
<Grid>
</Grid>
</Border>

Access ControlTemplate components (windows 8 app)

I would like to combine some UI elements into a Control, and then access them by code. However I can't figure it out.
The control template:
<Page.Resources>
<Style x:Key="GridViewStyle1" TargetType="GridView">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GridView">
<Grid>
<TextBox x:Name="theTextBox" Text="The Text" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
And a reference to the Template:
<GridView x:Name="myGridView1" Style="{StaticResource TileControl}"/>
So what I'm looking for is something like this for example:
myGridView1.Style.Template.Gridview.theTextBox.Text
But I can't find it. Any idea how I can do that? Or maybe I'm on the wrong track since it shouldn't be so complicated?
To retrieve ControlTemplate-generated element you can use something like (after the template has been applied to the control)
yourcontrol.Template.FindName("ControlElementTemplateToFind")
See also msdn

Button control template not working

i am written the following xaml code:
<Window x:Class="ImageScrollDemo.View.TestWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TestWindow" Height="300" Width="300">
<Window.Resources>
<Style x:Key="NextImageButtonStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Image Source="..\Images\#next.png" RenderOptions.BitmapScalingMode="HighQuality" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<Button Style="{DynamicResource NextImageButtonStyle}" />
</Grid>
</Window>
The window is rendered blank. i don't understand why.
<Image Source="..\Images\#next.png" ... />
Check the file name for the image and verify it does actually contain a # character.
Also, try using a static resource:
<Button Style="{StaticResource NextImageButtonStyle}" />
One thing to note: Try specifying TargetType using Type syntax
<Style x:Key="NextImageButtonStyle" TargetType="{x:Type Button}">
Reference: MSDN Style.TargetType Property
Using the key to refer to the resource may be enough, but an incorrect TargetType could interfere.

TemplateBinding not working with .NET framework objects

I am new to using the ControlTemplate. I am writing my first control but I am having (what seems to me) a very strange issue.
Any dependency properties that I make TemplateBinding to work, but any properties from the .NET framework objects i.e. the Content property of a ContentControl or the Items property of an ItemsControl does not get populated at runtime.
I am sure I am missing something... Just what it is I dont know...
An example of the code is below:
The class is very simple at the moment:
public class Title : ContentControl
{
}
And the Template is:
<Style TargetType="{x:Type UI:Title}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type UI:Title}">
<TextBlock Text="{TemplateBinding Content}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The base ContentControl class is the .NET class located in the System.Windows.Controls.Control namespace.
Thanks,
Adam
I believe if you'd like to override where the Content is placed you can do that using a ContentPresenter.
<Style TargetType="{x:Type UI:Title}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type UI:Title}">
<Label>
<ContentPresenter />
</Label>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Note I've also changed from a TextBlock to a Label as I believe the TextBlock.Text property will not accept everything from ContentControl.Content. Here is an example I put together that works as intended:
<Window x:Class="ContentControlTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ContentControlTest"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<Style TargetType="{x:Type local:Title}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:Title}">
<Button>
<ContentPresenter />
</Button>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<local:Title>
<TextBlock Text="Happy Days!" />
</local:Title>
</Window>
You may need to implement the INotifyPropertyChanged interface on your objects and INotifyCollectionChanged on your collections.

WPF: How to style or disable the default ContextMenu of a TextBox

Apparantly when users right-click in our WPF application, and they use the Windows Classic theme, the default ContextMenu of the TextBox (which contains Copy, Cut and Paste) has a black background.
I know this works well:
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<TextBox ContextMenu="{x:Null}"/>
</Page>
But this doesn't work:
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<Style x:Key="{x:Type TextBox}" TargetType="{x:Type TextBox}">
<Setter Property="ContextMenu" Value="{x:Null}"/>
</Style>
</Page.Resources>
<TextBox/>
</Page>
Does anyone know how to style or disable the default ContextMenu for all TextBoxes in WPF?
To style ContextMenu's for all TextBoxes, I would do something like the following:
First, in the resources section, add a ContextMenu which you plan to use as your standard ContextMenu in a textbox. e.g.
<ContextMenu x:Key="TextBoxContextMenu" Background="White">
<MenuItem Command="ApplicationCommands.Copy" />
<MenuItem Command="ApplicationCommands.Cut" />
<MenuItem Command="ApplicationCommands.Paste" />
</ContextMenu>
Secondly, create a style for your TextBoxes, which uses the context menu resource:
<Style TargetType="{x:Type TextBox}">
<Setter Property="ContextMenu" Value="{StaticResource TextBoxContextMenu}" />
</Style>
Finally, use your text box as normal:
<TextBox />
If instead you want to apply this context menu to only some of your textboxes, do not create the style above, and add the following to your TextBox markup:
<TextBox ContextMenu="{StaticResource TextBoxContextMenu}" />
Hope this helps!
Bizarre. ContextMenu="{x:Null}" doesn't do the trick.
This does, however:
<TextBox.ContextMenu>
<ContextMenu Visibility="Collapsed">
</ContextMenu>
</TextBox.ContextMenu>
Due to a late bug report we discovered that we cannot use the ApplicationComands Cut Paste and Copy directly in a partial trusted application. Therefor, using these commands in any Commmand of your controls will do absolutely nothing when executed.
So in essence Brads answer was almost there, it sure looked the right way i.e. no black background, but did not fix the problem.
We decided to "remove" the menu based on Brads answer, like so:
<ContextMenu x:Key="TextBoxContextMenu" Width="0" Height="0" />
And use this empty context menu like so:
<Style TargetType="{x:Type TextBox}">
<Setter Property="ContextMenu" Value="{StaticResource TextBoxContextMenu}" />
</Style>
Doesn't matter, if you do not provide a key, it will use the TargetType as key just the same way my example uses :)
Taken from MSDN on Style:
Setting the TargetType property to the TextBlock type without
setting an x:Key implicitly sets the x:Key to {x:Type TextBlock}. This also means that if you > > give the above Style an x:Key value of anything other than {x:Type TextBlock}, the Style
would not be applied to all TextBlock elements automatically. Instead,
you need to apply the style to the TextBlock elements explicitly.
http://msdn.microsoft.com/en-us/library/system.windows.style.targettype.aspx
This is way is what I always use:
<TextBox x:Name="MyTextbox">
<TextBox.ContextMenu>
<ContextMenu Visibility="Hidden"/>
</TextBox.ContextMenu>
</TextBox>
And also can use:
MyTextbox.ContextMenu.Visibility = Visibility.Hidden;
MyTextbox.ContextMenu.Visibility = Visibility.Visble;
Try removing the x:Key attribute from the Style resource, leaving TargetType. I know, you're supposed to have that x:Key for a resource, but if you have it along with your TargetType the Key prevails.
Here's a sample style that I use in a project to skin all tooltips in one of my apps (this is in App.Resources--notice, no Key)
<Style
TargetType="{x:Type ToolTip}">
<Setter
Property="Template">
<Setter.Value>
<ControlTemplate
TargetType="{x:Type ToolTip}">
<Grid
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}">
<Rectangle
RadiusX="9"
RadiusY="9"
Stroke="LightGray"
StrokeThickness="2">
<Rectangle.Fill>
<RadialGradientBrush>
<GradientStop />
<GradientStop
Color="FloralWhite"
Offset="0" />
<GradientStop
Color="Cornsilk"
Offset="2" />
</RadialGradientBrush>
</Rectangle.Fill>
</Rectangle>
<ContentPresenter
Margin="6 4 6 4" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Resources