WPF understand why textbox template into textblock still editable - c#

In my project i have created a template for my textbox, for test purpose i simplify it to this code:
<Window.Resources>
<Style x:Key="test" TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<TextBlock Text="{TemplateBinding Text}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<TextBox Style="{StaticResource test}" Grid.Row="2" Height="50" Width="200" Text="test">
</TextBox>
</Grid>
For what i understand, template erase how should be represented the textbox and show what i put in the template.
so when i put 'test' to the text TextBox, in reality it put it to the text Textbloc inside the textbox.
textbloc should be readonly, but on running if i clic on the label and tap on my keyboard, it still print key at the start of text (only add char at the start of text)...
(with binding it's editing the binding property...)
With a IsReadOnly="True" on the actual textbox it work as expected, but i don't understand why i need to do it.
I try on net6.0-windows and net5.0-windows, same result.
Is anymone understanding what i missing ?
Thank's for your time

Related

WPF ContentControl in ListViewItem is not changing it's width (not stretching) while dragging gridsplitter

So, I have a grid, containing 3 columns. 2 one is gridsplitter which is working fine.
In the first one I have a ListView
<ListView Grid.Row="1"
ItemsSource="{Binding Chats}"
Background="Transparent"
BorderThickness="0"
ItemContainerStyle="{StaticResource ContactItem}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"/>
Then there is Style: ContactItem
<Style TargetType="{x:Type ListViewItem}" x:Key="ContactItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<l:RippleEffectDecorator Background="Black" HighlightBackground="White">
<Border Height="62" Background="Transparent" BorderThickness="0">
</Border>
</l:RippleEffectDecorator>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
As you can see there is RippleEffectDecorator - which is ContentControl(I've found it in another case). There is link on github to it: Xaml file
And Cs file
So, starting the project I have:this
When I try to drag gridsplitter I have: this
I've already tried to put HorizontalAlignment and/or HorizontalContentAlignment Stretch to ListView/to ListViewItem style/to RippleEffectDecorator style.
Not problem about anything inside RippleEffectDecorator cuz when I was writing it without this contentcontrol it was working fine.
All I need is just everything inside this RippleEffectDecorator to be able to stretch horizontally when I'm moving gridsplitter, thank you!

Change TextBox Template without losing classic behavior

I've create a custom control which inherit from WPF TextBox.
My Control Template simply add a small button on textbox in order to delete its text quicker.
However, I've noticed that when my textBox got the focus, its border doesn't change (blue color) as is the case for classic textbox.
I would preserver all aspect of original textBox, just like the border when the control get focus.
Am I missing something?
##EDIT
<TextBox x:Class="XTextBox.WKTextBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
Height="23" Width="200"
>
<TextBox.Resources>
<ControlTemplate x:Key="IconButton" TargetType="{x:Type ToggleButton}">
<Border>
<ContentPresenter />
</Border>
</ControlTemplate>
</TextBox.Resources>
<TextBox.Style>
<Style TargetType="TextBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid>
<Border BorderThickness="1" BorderBrush="DarkGray">
<ScrollViewer x:Name="PART_ContentHost" />
</Border>
<ToggleButton Template="{StaticResource IconButton}"
MaxHeight="21"
Margin="-1,0,0,0"
Name="imgButton"
Focusable="False"
IsChecked="False">
<Image Name="imgClearText" Source="Images\x.png" Stretch="Uniform" Opacity="0.5" Visibility="Visible" HorizontalAlignment="Right" >
</Image>
</ToggleButton>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TextBox.Style>
Unfortunately, you can't simply Replace part of default template in WPF without loosing functionallity.
I believe the easiest solution would be to donwload Blend (it comes with VS2015). Open it, create an emty textbox and edit its template:
Blend will make a copy of default template, so you won't loose any of your default behaviour, like selection, focus etc.
Then you can save a project, open it in VS and refactor it as you want. Like moving style to dictionary or something.
You can manually get the same effect by adding handlers for the GotFocus & LostFocus events of the Border and set the highlight colors you want there.
<Border BorderThickness="1" BorderBrush="DarkGray" LostFocus="Border_LostFocus" GotFocus="Border_GotFocus">
and in your .cs file
private void Border_LostFocus(object sender, RoutedEventArgs e)
{
((Border)sender).BorderBrush = new SolidColorBrush(Colors.DarkGray);
}
private void Border_GotFocus(object sender, RoutedEventArgs e)
{
((Border)sender).BorderBrush = new SolidColorBrush(Colors.LightBlue);
}

Is it possible to provide 'arguments' to Custom control Styles & Templates?

I have 2 buttons, both of which are using a style to keep a consistent UI. However for 1 button, I would like to provide an image for, and the other just text.
I suppose I could create a new style, copy everything over, and the reformat it to my liking, but this seems like waste, is time consuming, and i think i would have to do it for each instance I wish to have a image on a button. I mean, that's fine, but I just want to know if there is an alternative that would make things more elegant.
I think I should somehow be able to push an 'arguement' or data to a style, either in or out of XAML to format the style, or something that would accomplish this (I'm sure the terminology is wrong).
Here is the Button Style:
<Style x:Key="Control_Button" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Image> <!-- Optional Image here --> </Image>
<TextBlock Name="btn" Text="{TemplateBinding Content}" Padding="16" VerticalAlignment="Center">
<TextBlock.TextDecorations>
<TextDecoration Location="Underline" />
</TextBlock.TextDecorations>
</TextBlock>
<!-- FIX ME: not underlined normally -->
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="TextBlock.IsMouseOver" Value="True">
<Setter TargetName="btn" Property="TextDecorations" Value="none" />
<!-- FIX ME: underlined on hover -->
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
What you are asking for is not possible without creating a custom control or user control.
What you should do though is setting the contents of the button the way you like. If you want only a string, you can set it directly:
<Button>my text</Button>
or with a binding:
<Button Content={Binding textProperty} />
To include an image in the button, add a panel as content, in this example I added a StackPanel, but you can also use a Grid or any other element:
<Button>
<Button.Content>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding myImagePath}" />
<TextBlock Text="{Binding myText}" />
</StackPanel>
</Button.Content>
</Button>

Reusable way to put a bright red box around whatever element currently has focus?

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>

WPF set image for a button in the C# code behind at runtime

I'm very new to WPF, so please bear with me.
Basically I have defined a Style in a WPF UserControl to show buttons with an image as follows:
<UserControl.Resources>
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">
<Image Width="16" Height="16" Stretch="UniformToFill"/>
<ContentPresenter/>
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
I then add a load of buttons to a grid at runtime (it has to be at run time as the number and type of button is dynamic).
What I would like to do is set the image of the buttons at runtime as well. I have tried a number of ways, but none seem to work. Setting the source in the Xaml works fine. The code I'm trying is as follows:
Button b = new Button();
// Create source.
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.UriSource = new Uri(#"C:\SourceCode\DSA\DSALibrary\Icons\money.png");
bi.EndInit();
b.SetValue(Image.SourceProperty, bi);
Could anybody point me towards where I'm going wrong, if I were to guess, I would say that where I think I'm setting the value, I'm actually not.
Cheers
You can try to use the Content property of Button, and declare a DataTemplate for handling the content:
<UserControl.Resources>
<Style TargetType="Button">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Width="16" Height="16" Stretch="UniformToFill" Source="{Binding}"/>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="My button text" />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<ContentPresenter/>
</ControlTemplate>
</Setter.Value>
</Setter>
</UserControl.Resources>
Set the BitmapImage on the content of your button, et voila :)
Can you confirm that it's a System.Windows.Controls.UserControl derived object you're creating?
My guess would be that the control loads it's bitmap when you create it so setting the image source property after that isn't being caught. Have you tried creating a button programmatically with a two-stage creation and setting it before you do the second stage?
You could try calling the button's Invalidate() function to make sure it redraws.

Categories