preventing label border from being bold - c#

I am using viewbox to fill the space available, it kind of gives me right result but not exactly.
<Viewbox Grid.Row="0" Grid.Column="0">
<StackPanel Name="letters" Orientation="Horizontal">
<Label ..>...</Label>
...
</StackPanel>
</Viewbox>
When I keep adding labels to the StackPanel when they exceed the container width they get smaller.
It's the behaviour I want, however I don't want labels' border to be 'bold' (because of viewbox).
How should I change my code structure?

I've modified kzen's answer to ensure that you don't have to explicitly define the style in code every time you add a new label to that stack panel. (Warning: coding in-place, but AFAIK, it should compile fine as is)
<Viewbox Grid.Row="0" Grid.Column="0">
<StackPanel Name="letters" Orientation="Horizontal">
<StackPanel.Resources>
<ResourceDictionary>
<Style TargetType="{x:Type Label}">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Margin" Value="0"/> <!-- not sure if this is also something you want -->
<Setter Property="Padding" Value="0"/> <!-- not sure if this is also something you want -->
</Style>
</ResourceDictionary>
</StackPanel.Resources>
<Label></Label>
...
</StackPanel>
</Viewbox>

Create a style for your labels with BorderThickeness property set to 0...
<Style x:Key="MyLabelStyle" TargetType="{x:Type Label}">
<Setter Property="BorderThickness" Value="0"/>
</Style>
<Viewbox Grid.Row="0" Grid.Column="0">
<StackPanel Name="letters" Orientation="Horizontal">
<Label Style="{DynamicResource MyLabelStyle}"></Label>
...
</StackPanel>
</Viewbox>

Anyway.. I should have asked if it's possible to have something constant size inside viewbox, that should have been more clear.

Related

Is there a way to add a resource to an UIElementCollection (like Grid.Children)?

in an XAML-File I have an Image defined as a resource. Of course I can assign it for instance as a content of a ContenControl (like a Button).
Is there a way in XAML to add such a resource to the Children of a Panel (like a Grid)
<!--Creation of the Image as a resource (in this case loaded from assembly ressources)-->
<ResourceDictionary>
<Image x:Key="CheckImage" x:Shared="False" Margin="0" Stretch="None" Source="/CheckStyleRes;component/CHECK.png" HorizontalAlignment="Center" VerticalAlignment="Center" IsHitTestVisible="True" SnapsToDevicePixels="True" UseLayoutRounding="True"/>
</ResourceDictionary>
...
<!--This is a workaround, putting the Image into an ContentControl and this into the Children-->
<Grid>
<Grid.Children>
<ContentControl x:Name="CheckMark" Content="{StaticResource CheckImage}"></ContentControl>
</Grid.Children>
</Grid>
...
<!--But is there a syntax to add {StaticResource CheckImage} directly to Grid.Children-->
<Grid>
<Grid.Children>
<Image FromRessourceOrSomthingLikeThat= "{StaticResource CheckImage}">
</Grid.Children>
</Grid>
I dont want an ImageSource as resource (then I could use the Source-Property of Image and create the Images in Children). My resource should be an ready to use Image. Thank you.
You could write
<Grid>
<StaticResourceExtension ResourceKey="CheckImage"/>
</Grid>
but you would usually not do that. It is not the typical way how child elements are added to their parents.
As noted in a comment below, you would not be able to set any attached property like Grid.Row, Grid.Column, Canvas.Left, Canvas.Top, DockPanel.Dock etc. on the child element, which makes the approach pretty useless.
Better declare a BitmapImage resource
<BitmapImage x:Key="CheckImage" UriSource="/CheckStyleRes;component/CHECK.png"/>
and add an Image like this:
<Grid>
<Image Source="{StaticResource CheckImage}" Stretch="None"
SnapsToDevicePixels="True" UseLayoutRounding="True"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
If you don't want to repeat all the property assignments each time you declare an Image like this, move them into a default Image Style like
<Window.Resources>
...
<Style TargetType="Image">
<Setter Property="Stretch" Value="None"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="UseLayoutRounding" Value="True"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
</Window.Resources>

WPF: PART_ContentHost not scrolling

I am trying to make a Log area within my application and the customer has requested the ability to cut/paste the log messages from this area.
I originally was using the following to setup the log area with scrolling, but this does not allow the user to select & copy text:
<ScrollViewer DataContext="{StaticResource Log}"
Content="{Binding Appender.Notification}"
Height="150">
<ScrollViewer.Resources>
<Style TargetType="{x:Type ScrollViewer}">
<Setter Property="HorizontalScrollBarVisibility" Value="Auto" />
<Setter Property="VerticalScrollBarVisibility" Value="Auto" />
</Style>
</ScrollViewer.Resources>
</ScrollViewer>
I found this solution to create a read only TextBox with select-able text:
<TextBox Name="LoggingTextBox"
Height="250"
Width="950"
DataContext="{StaticResource Log}"
Text="{Binding Appender.Notification}"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<TextBox.Style>
<Style TargetType="TextBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border x:Name="PART_ContentHost" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TextBox.Style>
</TextBox>
This works to allow the selection of text within the log area but the scrolling does not work. I added the properties for *ScrollBarVisibility (not in the original solution).
How can I get the scrolling to work using this TextBox styling?
The fix is pretty simple: just change your Border to a ScrollViewer, and you will get the standard scrolling behavior for a TextBox.

WPF XAML display content in a ContentControl

I need to display a number in a square, centered horizontally and vertically.
When I tried to use a label for that purpose, it seemed like it ignored the centering completely. So I decided to use a grid and display a label on the grid as that centers perfectly.
I need to use a template as there's several themes available. From what I've found on the internet, I thought this ( ignoring the centering for now )
<ControlTemplate x:Key="ClockTemplate">
<Grid>
<Grid.Style>
<Style TargetType="Grid">
<Setter Property="Background" Value="White"/>
</Style>
</Grid.Style>
<Label>
<Label.Style>
<Style TargetType="Label">
<Setter Property="Foreground" Value="#376092"/>
</Style>
</Label.Style>
<ContentPresenter/>
</Label>
</Grid>
</ControlTemplate>
would be correct. Using it as follows:
<ContentControl Content="20" Height="64" Width="64" Template="{DynamicResource ClockTemplate}"/>
the content is not displayed tho, what am I doing wrong? Also, is there a better way to achieve my goal?
As per my understanding this is not the correct approach. Instead of creating ControlTemplate you have to write a Style for your control like below, also use StaticResource binding if possible. It is faster than Dynamic binding. Please not that, I have not mentioned the Label size inside the ControlTemplate. Please do it based on your needs
<Style x:Key="ContentControlStyle"
TargetType="ContentControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Grid Background="White">
<Label Foreground="#376092"
Width="200"
Height="100" Content="{TemplateBinding Content}">
</Label>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
bind your ContentControl with the newly created Style like below
<ContentControl Style="{StaticResource ContentControlStyle} ">
If your requirement is only to set some value in ContentControl, use Label instead and change the Style of the Label. Because ContentControl is heavy

WPF: how to style a class like in css?

Let's say I have a UserControl with 4 Borders:
<Border />
<Border />
<Border />
<Border />
Now in my Resources I can go:
<Style TargetType="{x:Type Border}">
... change some properties here
</Style>
Now this is all good, but it will target all borders in my UserControl.
But what if I just want to target a subset of them?
I'd like to go:
<Border Class="Type1" />
<Border Class="Type1" />
<Border />
<Border />
And then go:
<Style TargetType="{x:Type Border}" TargetClass="Type1">
... change some properties here
</Style>
But this obviously doesn't exist, is there some other way I can achieve what I'm after?
Thanks
Though the syntax isn't quite as clean as in CSS, it is a lot more specific.
To build on your example, what you're looking for is:
<Border Style="{StaticResource Type1}" />
<Border Style="{StaticResource Type1}" />
<Border />
<Border />
And then go:
<Style TargetType="{x:Type Border}" x:Key="Type1">
... change some properties here
</Style>
Remember that WPF styles don't actually cascade like CSS does.
A more detailed styling reference:
https://web.archive.org/web/20141210000517/http://dotnetslackers.com/articles/wpf/StylesResourcesAndControlTemplatesInWPF.aspx
Something that I find most people are not aware of is WPF's ability to nest Styles within Style.Resources. For example:
<!-- Define a new style for Borders called InfoBox, that will have a red background,
and further override all buttons within it to have Yellow Text. An extra style,
"Strawberry" is also defined, that lets specific buttons be selected to be styled
as Green FG on DarkRed BG -->
<Style TargetType="{x:Type Border}" x:Key="InfoBox">
<Setter Property="Background" Value="Red"/>
<Style.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Foreground" Value="DarkYellow"/>
</Style>
<Style TargetType="{x:Type Button}" x:Key="Strawberry">
<Setter Property="Foreground" Value="Green"/>
<Setter Property="Background" Value="DarkRed"/>
</Style>
</Style.Resources>
</Style>
...
<Border Style="{DynamicResource InfoBox}">
<StackPanel>
<Button Content="I am a banana!"/>
<Button Style="{DynamicResource Strawberry}" Content="I am red!"/>
</StackPanel>
</Border>
While not exactly the same as CSS (There isn't much support for standard pseudo-selectors), this gives you a huge amount of power and flexibility. Couple this with skillful use of ItemsControls and you can do some great things.
you can set the style directly on the <Border> using an x:key and the StaticResource (or DynamicResource) property of the Border. if you would like to change the style at runtime, then you should lean towards using the DynamicResource over the StaticResource.
<Style x:Key="something" TargetType="{x:Type Border}">
</Style>
<Border style="{StaticResource something}"/>
<Style x:Key="styleKey" TargetType="{x:Type Border}">
... change some properties here
</Style>
and
<Border Style="{StaticResource styleKey}"

WPF ItemsControl IsMouseOver not working as expected

I have the following code in the Window.Resources of a WPF window. What it is basically doing is creating an item that represents a grid with a label positioned on the left and a button on the right. When I mouse over the label or the button the row changes color as expected but I want it to also change color if the mouse is over any of the row.
How can this be achieved?
Any help is appreciated.
<Window.Resources>
<dtos:ProjectDto x:Key="data"/>
<Style x:Key="alternatingWithTriggers"
TargetType="{x:Type ContentPresenter}">
<Setter Property="Height" Value="25"></Setter>
</Style>
<Style x:Key="onmouseover" TargetType="{x:Type DockPanel}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Yellow">
</Setter>
</Trigger>
</Style.Triggers>
</Style>
<DataTemplate x:Key="ItemTemplate">
<Border x:Name="ItemBorder" HorizontalAlignment="Stretch" BorderThickness="0" Background="#BBB" ClipToBounds="True" >
<DockPanel ClipToBounds="True" HorizontalAlignment="Stretch" Style="{StaticResource onmouseover}">
<Label Content="{Binding Name}" HorizontalAlignment="Left" Height="80"></Label>
<Button Content="Delete" HorizontalAlignment="Right" Margin="0,0,10,0"/>
</DockPanel>
</Border>
...
Give the DockPanel Background="Transparent". That should allow it to capture mouse events.
I don't see anything obviously wrong in the snippet you've posted, and since I'm not in front of Studio, I can't try it out, but if I were you, I'd try adding a MouseEnter handler on the DockPanel (just throw the do-nothing handler in the code-behind for the view, since you'll remove it later).
Make sure that handler is getting hit when you enter, and with the debugger/immediate window, make sure the IsMouseOver property is as you expect it to be. That will at least direct your next debugging steps:
If IsMouseOver is true and your handler is hit, then my guess would be something about the trigger you've got set up isn't quite right.
If IsMouseOver is false or your handler isn't hit, then my guess would be something like IsHitTestVisible is set to false or something of that sort.
Just for fun, I'd also try moving the style declaration inline to the dockpanel, just to make sure, like so:
<DataTemplate x:Key="ItemTemplate">
<Border x:Name="ItemBorder" HorizontalAlignment="Stretch" BorderThickness="0" Background="#BBB" ClipToBounds="True" >
<DockPanel ClipToBounds="True" HorizontalAlignment="Stretch">
<DockPanel.Style>
<Style TargetType="{x:Type DockPanel}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Yellow"/>
</Trigger>
</Style.Triggers>
</Style>
</DockPanel.Style>
<Label Content="{Binding Name}" HorizontalAlignment="Left" Height="80"></Label>
<Button Content="Delete" HorizontalAlignment="Right" Margin="0,0,10,0"/>
</DockPanel>
</Border>

Categories

Resources