I currently have an example that embeds an image object inside of a button.
the xaml looks like this:
<Button Height="194" HorizontalAlignment="Left"
Margin="23,27,0,0" Name="button1" VerticalAlignment="Top" Width="216"
Click="button1_Click">
<Image Name="image1" Stretch="Fill"
Source="/WPFButtonEmbedded;component/BenderInSpaceFace.png"
Height="105" VerticalAlignment="Bottom" Width="158" />
</Button>
However, when I try to recreate this myself i seem to get an error. I though that maybe they were binded togeather but looking at the example it doesnt seem that way.
Also the "image1" is an image that i added by clicking add exising item.
Any comments or suggestions are appreciated.
Thanks.
if you need to set image as Content
you can do it by setting style in resource
<Window.Resources>
<Image x:Key="Img" Source="/WPFButtonEmbedded;component/BenderInSpaceFace.png" Stretch="Fill"/>
<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Content" Value="{StaticResource Img}" />
</Style>
</Window.Resources>
then you can set the Style of the Button
<Button Style="{StaticResource ButtonStyle}" />
Related
I would like to know how to get a menu in the window bar, the same as Visual studio does.
It would be good to be able to have File, Edit, etc on the left and the standard Minimize, Maximize and Close buttons on the right. Is this at all possible?
I have tried setting Window WindowStyle="None" and adding my own icons in the bar but it doesnt seem right but is this the only way?
This is what i have at the moment.
<Window
Title="MainWindow"
Height="{x:Static SystemParameters.PrimaryScreenHeight}"
Width="{x:Static SystemParameters.PrimaryScreenWidth}"
Closing="Window_Closing"
WindowState="Maximized">
You must create your custom window chrome using the WindowChrome class:
The Window element in WPF is actually hosted in a non-WPF (non-client) host. This host includes the title bar (caption) and the standard buttons, an icon and the actual frame. This is known as window chrome.
Usually you can only modify the client area of a Window. But whith the help of the WindowChrome class, WPF allows the client area to extend into the non-client area.
The disadvantage is that you would have to basically replicate the original non-client area in order to preserve the original look and feel. But after all you still get some basic behavior like maximizing the window on double click ou of the box.
The following example is very basic, but should give you an idea how to achieve your task:
I highly recommend to follow the provided link to the WindowChrome class and read the remarks section, which contains very valuable information.
You can use the actual system values provided by the static SystemParameters class to get the current dimension values e.g. SystemParameters.WindowResizeBorderThickness which you should use in your custom chrome style.
Also note that to allow WPF to capture mouse events on you custom chrome's input elements like buttons or menus you must set the attached property WindowChrome.IsHitTestVisibleInChrome on each relevant element to true:
WindowChrome.IsHitTestVisibleInChrome="True"
The very basic style that creates the above visual is as followed:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:shell="clr-namespace:System.Windows.Shell;assembly=PresentationFramework">
<Style x:Key="WindowStyle" TargetType="{x:Type Window}">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="WindowChrome.WindowChrome">
<Setter.Value>
<WindowChrome NonClientFrameEdges="Right"
ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid Background="Transparent">
<AdornerDecorator>
<Border Background="Transparent" Margin="{x:Static SystemParameters.WindowNonClientFrameThickness}">
<ContentPresenter />
</Border>
</AdornerDecorator>
<ResizeGrip x:Name="WindowResizeGrip"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Visibility="Collapsed"
IsTabStop="false" />
<Grid Height="{Binding Source={x:Static SystemParameters.WindowNonClientFrameThickness}, Path=Top}"
Background="#FF3F3F3F"
VerticalAlignment="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<!-- Custom window chrome -->
<StackPanel Grid.Column="0" Orientation="Horizontal"
Margin="{x:Static SystemParameters.WindowResizeBorderThickness}">
<Image Source="{TemplateBinding Icon}" />
<TextBlock Text="{TemplateBinding Title}"
TextTrimming="CharacterEllipsis"
VerticalAlignment="Center"
Margin="16,0" />
<Menu shell:WindowChrome.IsHitTestVisibleInChrome="True">
<MenuItem Header="CustomChromeMenu">
<MenuItem Header="Action" />
</MenuItem>
</Menu>
</StackPanel>
<StackPanel Grid.Column="1"
Orientation="Horizontal"
HorizontalAlignment="Right">
<Button Width="45"
Height="{Binding Source={x:Static SystemParameters.WindowNonClientFrameThickness}, Path=Top}"
ToolTip="Minimize window"
ToolTipService.ShowDuration="5000"
shell:WindowChrome.IsHitTestVisibleInChrome="True">
<TextBlock Foreground="{Binding RelativeSource={RelativeSource AncestorType=Control}, Path=Foreground}"
FontFamily="Segoe MDL2 Assets"
FontSize="11"
Text="" />
</Button>
<Button ToolTip="Maximize window"
Width="45"
Height="{Binding Source={x:Static SystemParameters.WindowNonClientFrameThickness}, Path=Top}"
ToolTipService.ShowDuration="5000"
shell:WindowChrome.IsHitTestVisibleInChrome="True">
<TextBlock Foreground="{Binding RelativeSource={RelativeSource AncestorType=Control}, Path=Foreground}"
FontFamily="Segoe MDL2 Assets"
FontSize="11"
Text="" />
</Button>
<Button ToolTip="Close application"
ToolTipService.ShowDuration="5000"
Width="50"
Height="{Binding Source={x:Static SystemParameters.WindowNonClientFrameThickness}, Path=Top}"
shell:WindowChrome.IsHitTestVisibleInChrome="True">
<TextBlock Foreground="{Binding RelativeSource={RelativeSource AncestorType=Control}, Path=Foreground}"
FontFamily="Segoe MDL2 Assets"
FontSize="11"
Text="" />
</Button>
</StackPanel>
</Grid>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="ResizeMode"
Value="CanResizeWithGrip">
<Setter TargetName="WindowResizeGrip"
Property="Visibility"
Value="Visible" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
The title bar contains
An icon
A title
A minimize button
A maximize button
A close button
And that's all. You can't add anything.
In VS, the title bar is masked. The "title bar" you see is in fact the content of the window. That is, as you seemed to suspect, the only way.
That's also why tooltips on the three right buttons are in the OS language for most apps (because the title bar is managed by the system), but are in the app language for Visual Studio.
You have to set WindowStyle to None to mask the real title bar.
Then, inside your window, you should add a DockPanel and dock to the top an image and a menu on the left, and 3 buttons on the right.
The minimize button should change the WindowState to Minimized.
The maximize button should change the WindowState to either Normal or Maximized and its icon should be based on the WindowState.
The close button should call the Close() method and/or the Application.Current.Shutdown(0) method.
You should also subscribe to events like MouseLeftButtonDown, MouseLeftButtonUp and MouseMove to move the window.
I create in XAML RadGridVieaw controls custom tooltip and when tool tip before opening, I want read row and take ID and then load picture from database.
1 step I create custom tool tip
<Style TargetType="{x:Type telerik:GridViewRow}" BasedOn="{StaticResource GridViewRowStyle}" >
<Setter Property="ToolTipService.IsEnabled" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type telerik:RadGridView}}}" />
<Setter Property="ToolTip" >
<Setter.Value>
<ToolTip ToolTipService.ShowDuration="1000000" >
<Grid >
<Border HorizontalAlignment="Left" Height="170" Margin="5,0,0,0"
VerticalAlignment="Top" Width="130" BorderBrush="#FFCED8DA" BorderThickness="1" Padding="1">
<Image x:Name="GeneralTabItem_EmployeeImage" Source="{Binding CRAPhotoPhoto, Converter={StaticResource BinaryArrayToURIConverter}}" Stretch="UniformToFill"
Width="120" Height="160"/>
</Border>
<Grid/>
<telerik:RadGridView x:Name="ExtnedPrisonerInfoView_DataInput_ListGrid" HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Stretch" ToolTipService.ShowDuration="100000000"
DataContext="{Binding ''}" ToolTipOpening="OnContentChanged">
</telerik:RadGridView>
2 step I want to code behind catch event opening Tool tip.
3 step attach picture to the opening tool tip Image in Name="GeneralTabItem_EmployeeImage"
Please help me ToolTipOpening event is not working.
This should work as far as the event handler is concerned:
<Style TargetType="{x:Type telerik:GridViewRow}" BasedOn="{StaticResource GridViewRowStyle}" >
<EventSetter Event="ToolTipOpening" Handler="outerGrid_ToolTipOpening" />
...
But if you want to do something with the Image in the ToolTip, you need to wait until it has been created. You might as well handle the Loaded event of the Image and set the Source of it in there:
private void GeneralTabItem_EmployeeImage_Loaded(object sender, RoutedEventArgs e)
{
Image img = sender as Image;
//set source...
}
XAML:
<Setter Property="ToolTip" >
<Setter.Value>
<ToolTip ToolTipService.ShowDuration="1000000">
<Grid>
<Border HorizontalAlignment="Left" Height="170" Margin="5,0,0,0"
VerticalAlignment="Top" Width="130" BorderBrush="#FFCED8DA" BorderThickness="1" Padding="1">
<Image x:Name="GeneralTabItem_EmployeeImage" Stretch="UniformToFill"
Width="120" Height="160"
Loaded="GeneralTabItem_EmployeeImage_Loaded"/>
</Border>
<Grid/>
</Grid>
</ToolTip>
</Setter.Value>
</Setter>
Obviously you won't be able to set the Source property of an Image that resides in a ToolTip before the ToolTip has been opened because by then there is no Image. So this doesn't make much sense.
Create a simple tooltip first:
<Style TargetType="telerik:GridViewRow" BasedOn="{StaticResource
GridViewRowStyle}">
<Setter Property="ToolTip">
<Setter.Value>
<ToolTip>
<TextBlock Text="{Binding EmployeeName}"></TextBlock>
</ToolTip>
</Setter.Value>
</Setter>
</Style>
Verify that works and if it does start adding more complex things like converters and ToolTipService stuff one at a time to see what is it exactly that is invalidating your XAML because XAML error is the only reason why the event would not be firing...
I want to create a On/Off button in WPF and I want it to change its appearance when the user clicks it (if it was on switch to off, if it wad off switch to on) using images.
I added the images I want to use to the resources:
<Window.Resources>
<Image x:Key="Off1" Source="/WPFApplication;component/Images/off_button.png" Height="30" Width="70" />
<Image x:Key="On1" Source="/WPFApplication;component/Images/on_button.png" Height="30" Width="70"/>
</Window.Resources>
And the event code is, "flag" is a Boolean local variable initialize as true:
private void OnOff1Btn_Click(object sender, RoutedEventArgs e)
{
if (flag)
{
OnOff1Btn.Content = FindResource("Off1");
flag = false;
}
else
{
OnOff1Btn.Content = FindResource("On1");
flag = true;
}
}
Now I need to create 2 on/off buttons, that behave the same.
When I tried to use the same resources for the second button I got an exception:
Specified element is already the logical child of another element. Disconnect it first.
Can I use the same images resources in the second button or do I have to add the images again as resources with different Key?
Set Shared in your style to false
<StackPanel >
<StackPanel.Resources>
<Image x:Key="flag" Source="flag-italy-icon.png" Width="10" x:Shared="false"/>
</StackPanel.Resources>
<ContentControl Content="{DynamicResource flag}" />
<ContentControl Content="{DynamicResource flag}" />
You should use BitmapImage for image sharing.
<BitmapImage x:Key="Off1" UriSource="/WPFApplication;component/Images/off_button.png" Height="30" Width="70" />
<BitmapImage x:Key="On1" UriSource="/WPFApplication;component/Images/on_button.png" Height="30" Width="70"/>
After that you can create Multiple Image with BitmapImage
In XAML
<Button ..>
<Button.Content>
<Image Source="{StaticResource Off1}" />
</Button.Content>
</Button>
In Code
Image image = new Image();
image.Source = FindResource("Off1");
OnOff1Btn.Content = image;
While #Tilak's solution is definitely one way to go, you can also do this via Style.Triggers
Here's an example (with the assumption that Flag is a public property exposing flag):
<Button Content="{StaticResource On1}">
<Button.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Flag}" Value="false">
<Setter Property="Content" Value="{StaticResource Off1}" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
I'm attempting to create a simple button template in which the button normally looks like a single horizontal line, but when moused over, the button will display a "rectangle" color fill behind it. This is the code I have, but I can't seem to get the triggers to fire.
<Window x:Class="TestStylingWPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="36" GlassFrameThickness="0 0 0 1" ResizeBorderThickness="5" />
</WindowChrome.WindowChrome>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="36" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Button Height="36" Width="36"
HorizontalAlignment="Center" VerticalAlignment="Center"
Grid.Row="0">
<Button.Template>
<ControlTemplate>
<Grid>
<Rectangle x:Name="PART_ButtonBackgroundRectangle" Fill="LightGray" Width="36" Height="36" Opacity="0" />
<Path x:Name="PART_ButtonPath" Data="M10,26 L26,26" Stroke="DarkGray" StrokeThickness="1.5" />
</Grid>
<ControlTemplate.Triggers>
<Trigger SourceName="PART_ButtonBackgroundRectangle" Property="IsMouseOver" Value="True">
<Setter TargetName="PART_ButtonBackgroundRectangle" Property="Opacity" Value="1" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
</Window>
Does anyone know why my trigger won't work, or perhaps a better way to do this? I'm sort of new to WPF and would like to refactor this out (so as to use it in many buttons), but am unsure how.
Update: Ok, so I guess it appears to be because the button is within the caption bar of the window. Is there a good way around this? Maybe a way to set click/hover priority to the button?
You need to set Hittest visible of your button, such as:
shell:WindowChrome.IsHitTestVisibleInChrome="True"
I've got some windows with mainly comboboxes, textboxes, and checkboxes. When you click on one to get focus I need a way to have them be outlined with a colorful box (boss' orders). Is there a way to do this easier than overriding the default style of all of these controls? I've never done that before, so it would take a lot of mucking around on my part to figure it out.
You can try adding a FocusVisualStyle to the Controls that need different focus rectangle styles.
From above link
The second mechanism is to provide a separate style as the value of the FocusVisualStyle property; the "focus visual style" creates a separate visual tree for an adorner that draws on top of the control, rather than changing the visual tree of the control or other UI element by replacing it.
Something like this in your Window's Xaml
<Window.Resources>
<Style x:Key="NewFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Border>
<Rectangle Stroke="Red" Margin="2" StrokeThickness="1" StrokeDashArray="1 2" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
or your Application.Xaml file.
<Application.Resources>
<Style x:Key="NewFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Border>
<Rectangle Stroke="Red" Margin="2" StrokeThickness="1" StrokeDashArray="1 2" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
Usage:
<ComboBox FocusVisualStyle="{StaticResource NewFocusVisual}" Height="23" HorizontalAlignment="Left" Margin="238,102,0,0" Name="ComboBox1" VerticalAlignment="Top" Width="120" />
<CheckBox FocusVisualStyle="{StaticResource NewFocusVisual}" Content="CheckBox" Height="16" HorizontalAlignment="Left" Margin="238,71,0,0" Name="CheckBox2" VerticalAlignment="Top" />
<TextBox FocusVisualStyle="{StaticResource NewFocusVisual}" Height="23" HorizontalAlignment="Left" Margin="238,144,0,0" Name="TextBox1" VerticalAlignment="Top" Width="120" />
If you want the Focus rectangle to change for every type of focus event Microsoft states that:
From Microsoft: Focus visual styles act exclusively for keyboard focus. As such, focus visual styles are a type of accessibility feature. If you want UI changes for any type of focus, whether via mouse, keyboard, or programmatically, then you should not use focus visual styles, and should instead use setters and triggers in styles or templates that are working from the value of general focus properties such as IsFocused or IsFocusWithin.
Give this a shot it works for a TextBox haven't checked your other Controls
<Application.Resources>
<Style TargetType="TextBox" >
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Control.BorderBrush" Value="Red" />
<Setter Property="Control.BorderThickness" Value="3" />
</Trigger>
</Style.Triggers>
</Style>
</Application.Resources>