I have WPF Form which has many buttons with the same code. Appearance of all buttons must be the same
For example, code for one of these buttons
<Button x:Name="btnAddRelative" Width="120" Click="btnAddRelative_Click" >
<Button.Content>
<StackPanel Orientation="Horizontal">
<Image Height="26" HorizontalAlignment="Left">
<Image.Source>
<BitmapImage UriSource="images/add.png" />
</Image.Source>
</Image>
<TextBlock Text=" Add Relative" Height="20" VerticalAlignment="Center"/>
</StackPanel>
</Button.Content>
</Button>
How can I create one style and use it for all my buttons. All buttons has the same png image, only their text different. How can I do this.
I tried to do this with Style object in Resource Section:
<UserControl.Resources>
<Style TargetType="Button" x:Key="AddStyle">
<Setter Property="Content">
<Setter.Value>
<StackPanel Orientation="Horizontal">
<Image Height="26" HorizontalAlignment="Left">
<Image.Source>
<BitmapImage UriSource="images/add.png" />
</Image.Source>
</Image>
<TextBlock Text=" " Height="20" VerticalAlignment="Center"/>
</StackPanel>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
But this code not work. Can any body know how can I do this?
If the image is fix you can hard-code it in the style, and use the Content property of Button bin to the Content of TextBox
<Style x:Key="ButtonStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<StackPanel
Orientation="Horizontal">
<!--<Image Height="26" HorizontalAlignment="Left">
<Image.Source>
<BitmapImage UriSource="images/add.png" />
</Image.Source>
</Image>-->
<TextBlock
Foreground="{TemplateBinding Foreground}"
Text="{TemplateBinding Content}"
Height="20"
VerticalAlignment="{TemplateBinding VerticalAlignment}"/>
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
just try this
<Window.Resources>
<Style TargetType="Button"
x:Key="AddStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<StackPanel Orientation="Horizontal">
<Image Height="26"
Width="20"
HorizontalAlignment="Left">
<Image.Source>
<BitmapImage UriSource="/WpfApplication33;component/Images/MoveLeft.png" />
</Image.Source>
</Image>
<TextBlock Text ="{TemplateBinding Content}"
Height="20"
/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<StackPanel>
<Button Style="{StaticResource AddStyle}"
Height="25" Width="100"
Content="Button1"></Button>
<Button Style="{StaticResource AddStyle}"
Height="25"
Width="100"
Content="Button22"></Button>
<Button Style="{StaticResource AddStyle}"
Height="25"
Width="100"
Content="Button2233"></Button>
<Button Style="{StaticResource AddStyle}"
Height="25"
Width="100"
Content="Button2332"></Button>
</StackPanel>
</Grid>
Note: Use ContentPresenter instead of TextBlock if you have to display anything other than flat text
Try changing your style as follows
<UserControl.Resources>
<Style
TargetType="Button"
x:Key="AddStyle">
<Setter
Property="Template">
<Setter.Value>
<ControlTemplate>
<StackPanel
Orientation="Horizontal">
<Image
Height="26"
HorizontalAlignment="Left">
<Image.Source>
<BitmapImage
UriSource="images/add.png" />
</Image.Source>
</Image>
<TextBlock
Text=" "
Height="20"
VerticalAlignment="Center" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
[Edit inspired by comment]
You could create a new UserControl, lets call it AddButtonContent containing your Stackpanel and such, then include that within your button, like so:
<Button>
<local:AddButtonContent
ButtonText="Testing, one, two, three" />
</Button>
You'll need to add a xmlns reference called local (or whatever you'd like to call it) to the UserControl with all of the buttons.
The codebehind portion of your AddButtonContent UserControl will need the following code, and you'll need to name your TextBlock (I used testText for this example).
public static DependencyProperty ButtonTextProperty =
DependencyProperty.Register("ButtonText",
typeof(string),
typeof(AddButtonContent),
new PropertyMetadata("", onTextChangedCallback));
public string ButtonText
{
get { return (string)GetValue(ButtonTextProperty); }
set
{
SetValue(ButtonTextProperty, value);
}
}
static void onTextChangedCallback(
DependencyObject dobj,
DependencyPropertyChangedEventArgs args)
{
AddButtonContent abc = dobj as AddButtonContent;
abc.testText.Text = args.NewValue.ToString();
}
Related
I'm using a ListViewto display a menu. I want to apply a style to all ListViewItem. So far I have succeeded in one part of the concern but I would like to improve to avoid code replication. Here where I am :
<Window.Resources>
<Style x:Key="_listViewItemStyle" TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border x:Name="Bd"
...
</Border>
<ControlTemplate.Triggers>
...
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
And then use the style like that :
<ListView x:Name="_listViewMenu"
Background="Transparent"
BorderBrush="Transparent"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListViewItem Style="{StaticResource _listViewItemStyle}">
<StackPanel Orientation="Horizontal"
Width="230"
Margin="10,0,0,0">
<Image Width="30"
Source="Images/Settings.png"
Stretch="Uniform"/>
<TextBlock Text="Paramètres"
Margin="25,0,0,0"
Style="{StaticResource _fontStyle}"/>
</StackPanel>
</ListViewItem>
</ListView>
As you can see there are some stuff that I imagine I can avoid to duplicate if I have 50 ListViewItems, let's say :
<StackPanel Orientation="Horizontal"
Width="230"
Margin="10,0,0,0">
or
<Image Width="30"
...
Stretch="Uniform"/>
etc...
How to include in the style _listViewItemStyle all required properties to format StackPanel, Image, textbox, etc... of the ListViewItem?
Thanks.
You can define a class which has necessary properties and use it as item type of collection for ItemsSource which may be in view (xaml or code behind). Such class would be as follows.
public class SourceItem
{
public string? ImagePath { get; init; }
public string? Text { get; init; }
}
Then, if you just want to show items, ItemsControl would be suffice. I don't know how you intend to use Triggers though.
<ItemsControl Background="Blue" HorizontalAlignment="Left">
<local:SourceItem ImagePath="Images/Settings.png" Text="Paramètres"/>
...
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border x:Name="Bd">
<StackPanel Orientation="Horizontal"
Width="230"
Margin="10,0,0,0">
<Image Width="30"
Source="{Binding ImagePath, Mode=OneTime}"
Stretch="Uniform"/>
<TextBlock Text="{Binding Text, Mode=OneTime}"
Margin="25,0,0,0"
Style="{StaticResource _fontStyle}"/>
</StackPanel>
</Border>
<DataTemplate.Triggers>
...
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
In addition to the answer from #emoacht, you will need the following InputBindings:
<Border.InputBindings>
<MouseBinding Command="{Binding ItemCommand}" MouseAction="LeftClick"/>
</Border.InputBindings>
I have created a Groupbox resource directory, and created a style that affects the groupbox.
Here is my Resource Directory code:
<Style x:Key="grpNumbers" TargetType="GroupBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GroupBox">
<Border
BorderThickness="1"
BorderBrush="#25A0DA" CornerRadius="10">
<Label HorizontalAlignment="Left" Content="Carrier" Foreground="White" Background="#151515" Height="38"
Margin="30,-195,0,0"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The issue is that I want the group box style to not be coupled with the Content in the Label.
Currently it is getting instantiated in the mainwindow like this:
<GroupBox Style="{StaticResource ResourceKey=grpNumbers}" Grid.Column="1" BorderBrush="#272727" Grid.Row="1" Height="200" Margin="20" HorizontalAlignment="Stretch" Header="Carrier information" Foreground="White" FontSize="20" BorderThickness="0.2">
</GroupBox>
But obviously the above groupboxes' Header tag isn't overriding the header of my custom groupbox but I need it too, can this be done?
Label inside ContentTemplate can use TemplateBinding to bind Header:
<Label Content="{TemplateBinding Header}"/>
You should modify your Style too look like this:
<Style x:Key="grpNumbers" TargetType="{x:Type GroupBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupBox}">
<Grid>
<Border BorderThickness="1"
BorderBrush="#25A0DA"
CornerRadius="10">
<Label HorizontalAlignment="Left"
Content="{TemplateBinding Header}"
Foreground="White"
Background="#151515"
Height="38"
Margin="30,-195,0,0"/>
</Border>
<!-- Responsible for displaying what you put inside of your GroupBox -->
<ContentPresenter Margin="5,25,5,5" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
which can then be used like this:
<GroupBox Style="{StaticResource grpNumbers}"
Grid.Column="1"
BorderBrush="#272727"
Grid.Row="1"
Height="200"
Margin="20"
HorizontalAlignment="Stretch"
Header="Carrier information"
Foreground="White"
FontSize="20"
BorderThickness="0.2">
<TextBox /> <!-- or whatever you want inside your GroupBox -->
</GroupBox>
I'm using MaterialDesignInXaml for stylize my application. Said that, I'm using a ListView with a CollectionViewGroup for group my items, anyway, in the GroupStyle I've this structure:
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Expander IsExpanded="True">
<Expander.Header>
<DockPanel Height="16.5">
<TextBlock Text="{Binding Name.Name}" FontWeight="Bold" Foreground="White" FontSize="11.5" VerticalAlignment="Bottom" />
<TextBlock Text="{Binding ItemCount}" FontSize="11.5" Foreground="Orange" FontWeight="Bold" FontStyle="Italic" Margin="10,0,0,0" VerticalAlignment="Bottom" />
</DockPanel>
</Expander.Header>
<Border Style="{DynamicResource MaterialDesignPaper}">
<ItemsPresenter />
</Border>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
Now the problem is on this line: <Border Style="{DynamicResource MaterialDesignPaper}">, if I remove the border all working well, but with the xml above I get this exception:
System.Windows.Markup.XamlParseException: Unable to cast objects of type 'System.Windows.Media.SolidColorBrush' to type 'System.Windows.Style'. ---> System.InvalidCastException: Can not cast objects of type 'System.Windows.Media.SolidColorBrush' on the type 'System.Windows.Style'.
why happen this?
MaterialDesignPaper is a Brush, not a Style.
Therefore, depending on your requirement, you want something like this:
<Border BorderBrush="{DynamicResource MaterialDesignPaper}" />
or
<Border Background="{DynamicResource MaterialDesignPaper}" />
All Material Design In XAML Brushes are listed here: https://github.com/ButchersBoy/MaterialDesignInXamlToolkit/wiki/Brush-Names
When I set image as Header of TabItem it looks like image in some gray area. How remove this surrouding area?
<TabControl TabStripPlacement="Left"
HorizontalContentAlignment="Left"
VerticalContentAlignment="Top">
<TabItem ToolTip="Элементы, в которых найдены несоответствия" Height="200"
Style="{StaticResource TabItemHeaderImageStyle}">
<TabItem.Header>
<Image Source="{StaticResource CheckImage}"
Margin="0"
Height="25" Width="25" />
</TabItem.Header>
<ListBox ItemsSource="{Binding unmatched.vs}"
MaxHeight="200"
ItemTemplate="{StaticResource VertexPresenterNotConformTemplate}" />
</TabItem>
<TabItem ToolTip="Элементы, соответствующие шаблону"
Style="{StaticResource TabItemHeaderImageStyle}">
<TabItem.Header>
<Image Source="{StaticResource UncheckImage}"
Height="25" Width="25" />
</TabItem.Header>
<ListBox ItemsSource="{Binding unmatched.vs}"
MaxHeight="200"
ItemTemplate="{StaticResource VertexPresenterConformTemplate}" />
</TabItem>
<Style x:Key="TabItemHeaderImageStyle" TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border Name="Border"
Margin="0,0,-4,0"
BorderThickness="1,1,1,1"
CornerRadius="2,12,0,0" >
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="12,2,12,2"
RecognizesAccessKey="True"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
What I wish(TabItem's headers under each other without a gray area around it):
TabItem probably has a border around it's header that's gray (thus making a shadow around an image). See this link for TabItem ControlTemplate.
I'd try fiddling with the controltemplate or use an app like WpfInspector to see what's wrong with the template and get correct values.
I have the following control template.
I wish to set the source property for the image control in the control
template using Template Binding.
But since this is a control template for button control and the button control doesn't
have source property, i can't use TemplateBinding in this case.
<ControlTemplate x:Key="BtnTemplate" TargetType="Button">
<Border CornerRadius="5" Margin="15" Cursor="Hand">
<StackPanel>
<Image Name="Img" Style="{StaticResource ImageStyle}" Source="temp.jpg" Height="100" Width="100" Margin="5"></Image>
<Label Content="{TemplateBinding Content}" Background="Transparent" Margin="2"></Label>
</StackPanel>
</Border>
</ControlTemplate>
Since i have to set different images for different instances of button, i can't hardcode the path as well.
Please let me know how to tackle this situation.
I'd suggest using dynamic resources, e.g. define the template as follows:
<ControlTemplate x:Key="buttonTemplate" TargetType="Button">
<Border CornerRadius="5" Margin="15" Cursor="Hand">
<StackPanel Orientation="Horizontal" Background="Yellow">
<Image Source="{DynamicResource ResourceKey=Img}" Height="100" Width="100" Margin="5"></Image>
<Label Content="{TemplateBinding Content}" Background="Transparent" Margin="2"></Label>
</StackPanel>
</Border>
</ControlTemplate>
And use it like this:
<Button Content="Button" Template="{StaticResource ResourceKey=buttonTemplate}">
<Button.Resources>
<ImageSource x:Key="Img">SomeUri.png/</ImageSource>
</Button.Resources>
</Button>
TemplateBinding is a lightweight "binding", it doesn't support some features of traditional Binding, such as automatically type conversion using the known type converters associated with the target property (such as converting the string URI into a BitmapSource instance).
The following code can work properly:
<Window x:Class="GridScroll.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window2">
<Window.Resources>
<Style TargetType="{x:Type Button}" x:Key="ButtonStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border CornerRadius="5" Margin="15" Cursor="Hand" Background="Red">
<StackPanel Orientation="Horizontal" Background="White">
<Image Name="Img" Source="{Binding Path=Tag, RelativeSource={RelativeSource TemplatedParent}}" Margin="5"></Image>
<Label Content="{TemplateBinding Content}" Margin="2"></Label>
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<StackPanel Orientation="Horizontal">
<Button Style="{StaticResource ButtonStyle}" Tag="a.jpeg" Content="a"/>
<Button Style="{StaticResource ButtonStyle}" Tag="b.png" Content="b"/>
</StackPanel>
You haven't really said how you expect consumers of your button to set the source. You could use the Button.Tag property, for example, and then bind to that in your template. Or you could define your own control:
public class ImageButton : Button
{
// add Source dependency property a la Image
}
And then the template:
<ControlTemplate TargetType="ImageButton">
<Border CornerRadius="5" Margin="15" Cursor="Hand">
<StackPanel>
<Image Name="Img" Style="{StaticResource ImageStyle}" Source="{TempateBinding Source}" Height="100" Width="100" Margin="5"></Image>
<Label Content="{TemplateBinding Content}" Background="Transparent" Margin="2"></Label>
</StackPanel>
</Border>
</ControlTemplate>
I'm not sure that I understood your problem very well but why don't you use ContentPresenter? It allows to move the code for your Image at the higher level.
<ControlTemplate x:Key="BtnTemplate" TargetType="Button">
...
<ContentPresenter/>
</ControlTemplate>
...
<Button Template="{StaticResource BtnTemplate}">
<Image .../>
</Button>