I try to add button from code and add triggers and setters to it. I wolud like to create button like this:
<Button Height="25" Width="100" Name="TestColorButton" Margin="10, 5, 0, 0">
<TextBlock Text="{Binding Text, ElementName=ColorTextBox}"></TextBlock>
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="{Binding Fill, ElementName=NormalRectangle}"/>
<Setter Property="Template"> <!-- I need this setter -->
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{Binding Fill, ElementName=MouseOverRectangle}"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="{Binding Fill, ElementName=ClickRectangle}"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
I found how to do everything except one setter. I checked it by comment. I tried many times and I got only something like this:
ContentPresenter contentPresenter = new ContentPresenter
{
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center
};
Border border = new Border();
var binding = new Binding("Background");
binding.RelativeSource = new RelativeSource(RelativeSourceMode.Self);
BindingOperations.SetBinding(border, BackgroundProperty, binding);
border.Child = contentPresenter;
ControlTemplate controlTemplate = new ControlTemplate(typeof (Button));
Setter templateSetter = new Setter(TemplateProperty, controlTemplate);
style.Setters.Add(templateSetter);
I know it can not work, but I don't know how to do it differently.
Template can be added by code easily. here an example with a label.
// create the label with some context
var lbl = new Label() { DataContext = new ImageData(imagePath) };
// control template i want to put on the label
ControlTemplate labelLayout = new ControlTemplate();
// will be my main container that will be by template later on
FrameworkElementFactory grdContainer = new FrameworkElementFactory(typeof(Grid));
grdContainer.Name = "myContainer";
// another element but ill put it in the grid (template)
FrameworkElementFactory myImage = new FrameworkElementFactory(typeof(Image));
// some bindings and setters
myImage.SetBinding(Image.SourceProperty, new Binding("ImagePath"));
myImage.SetValue(Image.HorizontalAlignmentProperty, HorizontalAlignment.Center);
myImage.SetValue(Image.HeightProperty, height);
myImage.SetValue(Image.WidthProperty, double.NaN);
myImage.SetValue(Image.SnapsToDevicePixelsProperty, true);
// add the image to the grid
grdContainer.AppendChild(myImage);
// set the visual layout of the template to be the grid (main container)
labelLayout.VisualTree = grdContainer;
// set the template (line you are looking for mostly)
lbl.Template = labelLayout;
Related
I have style resource in my button to make it rounded, and i want to create it using c#(code behind), how do i do it?
<Button.Resources>
<Style TargetType="Border">
<Setter Property="CornerRadius" Value="5"/>
</Style>
</Button.Resources>
Create the Style:
Style style = new Style() { TargetType = typeof(Border) };
style.Setters.Add(new Setter() { Property = Border.CornerRadiusProperty, Value = new CornerRadius(5) });
style.Seal();
Add it to the Button:
button.Resources.Add(typeof(Border), style);
XAML:
<Button x:Name="button" Content="..." />
I created style like this:
<Window.Resources>
<Style x:Key="WejStyle" TargetType="{x:Type TabItem}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Header" Value="Wej"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<TextBlock TextWrapping="Wrap" Text="Adress(hex)" FontSize="15" Margin="10,10,396,355"/>
<ComboBox x:Name="WejAdress" HorizontalAlignment="Left" Margin="134,11,0,0" VerticalAlignment="Top" Width="120">
<ComboBoxItem>3A</ComboBoxItem>
<ComboBoxItem>3B</ComboBoxItem>
<ComboBoxItem>3C</ComboBoxItem>
<ComboBoxItem>3D</ComboBoxItem>
<ComboBoxItem>3E</ComboBoxItem>
<ComboBoxItem>3F</ComboBoxItem>
</ComboBox>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
And use method to add Item to TabControl
public void AddWej()
{
var resources = new Resources();
var style = (Style)resources.FindResource("WejStyle");
TabCards.Items.Add(style);
}
But it only return System.Windows.Stylein header and grid.
Can someone tell me what do I wrong?
Edit:
I change AddWej()
public void AddWej()
{
var resources = new Resources();
var style = (Style)resources.FindResource("WejStyle");
var tabItem = new TabItem();
tabItem.Style = style;
tabItem.Header = "Wej";
TabCards.Items.Add(tabItem);
//dodanie
cards.Add(new CardWej() { });
}
And code in xaml from:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
to
<Setter Property="ContentTemplate" >
<Setter.Value>
<DataTemplate>
And it work.
How do I apply a style not on the whole textblock, but only on the first run (the Bold)?
I want to apply the style "XXXFontName-Bold" on the Bold Run AND the style "XXXFontName-Thin" on the rest.
// add button
Button btn = new Button();
TextBlock contextText = new TextBlock();
contextText.Inlines.Add(new Bold(new Run(label.Substring(0,1))));
contextText.Inlines.Add(new Style()); <===== OBVIOUS ERROR HERE
contextText.Inlines.Add(label.Substring(1));
contextText.FontSize = 25;
contextText.Style = FindResource("XXXFontName-Thin") as Style;
btn.Content = contextText;
3 Example Styles, Example to set runs in XAML with the styles and new lines and also how to set them in the code behind in your button
Your code behind:
public MainWindow()
{
InitializeComponent();
Button btn = new Button();
TextBlock contextText = new TextBlock();
var newRun = new Run("BoldGreenRunStyle");
newRun.Style = FindResource("BoldGreenRunStyle") as Style;
contextText.Inlines.Add(newRun);
newRun = new Run("ItalicRedRunStyle");
newRun.Style = FindResource("ItalicRedRunStyle") as Style;
contextText.Inlines.Add(newRun);
newRun = new Run("ThinPurpleRunStyle");
newRun.Style = FindResource("ThinPurpleRunStyle") as Style;
contextText.Inlines.Add(newRun);
btn.Content = contextText;
Container.Children.Add(btn);
}
Your XAML
<Window.Resources>
<Style TargetType="Run" x:Key="BoldGreenRunStyle">
<Setter Property="Foreground" Value="Green"></Setter>
<Setter Property="FontWeight" Value="Bold"></Setter>
</Style>
<Style TargetType="Run" x:Key="ItalicRedRunStyle">
<Setter Property="Foreground" Value="Red"></Setter>
<Setter Property="FontWeight" Value="Normal"></Setter>
<Setter Property="FontStyle" Value="Italic"></Setter>
</Style>
<Style TargetType="Run" x:Key="ThinPurpleRunStyle">
<Setter Property="Foreground" Value="Purple"></Setter>
<Setter Property="FontWeight" Value="Thin"></Setter>
</Style>
</Window.Resources>
<StackPanel x:Name="Container">
<Label Content="From XAML"></Label>
<TextBlock>
<TextBlock.Inlines>
<Run Style="{StaticResource BoldGreenRunStyle}">BoldGreenRunStyle</Run>
<LineBreak/>
<Run Style="{StaticResource ItalicRedRunStyle}">ItalicRedRunStyle</Run>
<LineBreak/>
<Run Style="{StaticResource ThinPurpleRunStyle}">ThinPurpleRunStyle</Run>
<LineBreak/>
</TextBlock.Inlines>
</TextBlock>
</StackPanel>
I have an application named App Window. In which i need to display the installed apps in the tab items. Each tab item contains the data about its corresponding application. If a new app installed, then window will create a new tab item for the newly installed app.
*I have done upto creating a new tab item as per the installed applications.
Code i used:
private List<TabItem> _tabItems;
private TabItem _tabAdd;
try
{
_tabItems = new List<TabItem>();
InstalledApps.DataContext = _tabItems;
InstalledApps.SelectedIndex = 0;
if (A Installed)
this.AddTabItem("A");
if (B Installed)
this.AddTabItem("B");
}
catch (Exception ex)
{
}
private TabItem AddTabItem(string AppName)
{
int count = 1;
// create new tab item
TabItem tab = new TabItem();
tab.Header = AppName;
string tabName = AppName.ToLower();
tab.Name = tabName;
tab.HeaderTemplate = InstalledApps.FindResource("TabHeader") as DataTemplate;
TextBox txt = new TextBox();
txt.IsReadOnly = true;
tab.Content = txt;
_tabItems.Insert(count - 1, tab);
return tab;
}
Xaml:
<TabControl Height="555" HorizontalAlignment="Left" Margin="0,-27,0,0" Name=" InstalledApps " ItemsSource="{Binding}" BorderThickness="0,0,0,0" SelectionChanged=" InstalledApps_SelectionChanged" VerticalAlignment="Top" Width="992" Grid.ColumnSpan="3" Grid.RowSpan="4">
<TabControl.Resources>
<Style TargetType="TabItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<Grid Name="Panel">
<ContentPresenter x:Name="ContentSite" VerticalAlignment="Center"
HorizontalAlignment="Center" ContentSource="Header" Margin="80,10" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Panel" Property="Background" Value="#FFEFEFEF" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="Panel" Property="Background" Value="#FFE0E0E0" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding Items.Count, RelativeSource={RelativeSource Self}}" Value="0">
<Setter Property="Visibility" Value="Hidden" />
</DataTrigger>
</Style.Triggers>
</Style>
<DataTemplate x:Key="TabHeader" DataType="TabItem">
<DockPanel>
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=TabItem }, Path=Header}" />
</DockPanel>
</DataTemplate>
</TabControl.Resources>
</TabControl>
My requirement is:
While i am selecting anyone tab from the listed tab items, then it should show its corresponding contents(logo, app name) in is content part.
Thanks in advance,
Kathiresan S.
Create class representing the data you want to display. e.g:
public class AppDetails {
public Uri Logo { get; set; }
public string AppName { get; set; }
//etc
}
then set the AppDetails to TabItem.Content and define TabItem.ContentTemlate similarly as you did with HeaderTemplate.
tab.ContentTemplate = InstalledApps.FindResource("TabContent") as DataTemplate;
tab.Content = new AppDetails{ ... };
alternatively, you can skip ContentTemplate and assign some FrameworkElement (e.g. custom UserControl) directly to the tab content:
tab.Content = new AppDetailsUserControl(AppName, Logo);
Ans to If a new app installed, then window will create a new tab item for the newly installed app.
you should bind the DataContext of TabControl to ObservableCollection so that any new Tabitem added by backend will be shown UI directly.
Ans to While i am selecting anyone tab from the listed tab items, then it should show its corresponding contents(logo, app name) in is content part
You should set the content tab.Content to a UserControl or Model (if Model then define DataTemplate in ResourceDictionary). UserControl or DataTemplate can define what information should be displayed at what control and their visual hierarchy.
I want to use the same style for two controls, just change two background colors that are deep in its hierarchy.
I have a TextBox, a style for its ScrollViewer, a style and a template for its ScrollBar with a Background for its Border and a style for its Thumb with a Background for its Border.
How can I change The two backgrounds (programmatically or not) using only the TextBox?
.........
..........
..........
<!-- ScrollBar Style -->
<Style x:Key="{x:Type ScrollBar}" TargetType="ScrollBar">
....
<Style.Triggers>
<Trigger Property="Orientation" Value="Horizontal">
....
<Setter Property="Template" Value="{StaticResource HorizontalScrollBarTemplate}"/>
....
</Trigger>
</Style.Triggers>
</Style>
<!-- Horizontal Scrollbar Template -->
<ControlTemplate x:Key="HorizontalScrollBarTemplate" TargetType="{x:Type ScrollBar}">
<Grid Background="{StaticResource ScrollBackroundBrush}">
<Track Name="PART_Track">
<Track.Thumb>
<Thumb Style="{StaticResource ScrollBarThumb}"/>
</Track.Thumb>
</Track>
</Grid>
</ControlTemplate>
<!-- Thumb Style -->
<Style x:Key="ScrollBarThumb" TargetType="{x:Type Thumb}">
....
<Setter Property="Template">
....
<Border
....
Background="{StaticResource ScrollThumbBrush}"/>
....
</Setter>
</Style>
Is there a way to change the two backgrounds (to use this color and another same scrollviewer on another control perhaps with another color) without rewriting the whole code?
For example to have its style and write:
TextBox tb1 = new TextBox();
tb1.Style = /*style*/
tb1.BackgroundOfScroll = /*brush11*/
tb1.BackgroundOfThumb = /*brush12*/
TextBox tb2 = new TextBox();
tb2.Style = /*style*/
tb2.BackgroundOfScroll = /*brush21*/
tb2.BackgroundOfThumb = /*brush22*/
I made corresponding example. If you had only one color to set you could use Tag property since it is DependencyProperty. Create then two attached properties and get to them as follows:
<Button local:Color.CustomBackground="CadetBlue">
<Button.Template>
<ControlTemplate TargetType="Button">
<ContentPresenter>
<ContentPresenter.ContentTemplate>
<ItemContainerTemplate>
<Border Width="50" Height="{Binding RelativeSource={RelativeSource Self}, Path=Width}"
Background="{Binding RelativeSource={RelativeSource AncestorType=Button}, Path=(local:Color.CustomBackground)}">
</Border>
</ItemContainerTemplate>
</ContentPresenter.ContentTemplate>
</ContentPresenter>
</ControlTemplate>
</Button.Template>
</Button>
C#
public class Color : DependencyObject
{
private static readonly DependencyProperty CustomBackgroundProperty =
DependencyProperty.RegisterAttached("CustomBackground", typeof(SolidColorBrush), typeof(Color),
new PropertyMetadata(null));
public static void SetCustomBackground(DependencyObject obj, SolidColorBrush color)
{
obj.SetValue(CustomBackgroundProperty, color);
}
public static SolidColorBrush GetCustomBackground(DependencyObject obj)
{
return (SolidColorBrush)obj.GetValue(CustomBackgroundProperty);
}
}