how can I increase font of a, let's say, TextBlock? I don't want to have something like this:
<TextBlock FontSize="20">
text
</TextBlock>
because it won't work correctly when user changes Windows' settings of the controls' font size. Do we have something like +VALUE (eg. +2), similar to HTML?
EDIT
That's what I meant talking about the Windows' settings:
but the answers I received totally satisfies me.
WPF doesn't have the em font size, there alternatives in the answers to this SO
The simplist may be
<ScaleTransform ScaleX="1.2" ScaleY="1.2" />
Adapting Bob Vale's answer to your original code
<TextBlock>
<TextBlock.RenderTransform>
<ScaleTransform ScaleX="1.2" ScaleY="1.2" />
</TextBlock.RenderTransform>
text
</TextBlock>
First of all you should create an application scoped style for you font sizes, as described in this answer : WPF global font size
Then, you can bind the fontsize values to a property of a static class taking the size defined in control panel, and adapt it accordingly.
For those poor souls who find this questions in need for a relative font size mechanism for design purposes such as you'd use in css, I found a hack that appears to work in WPF.
It's used this way:
<StackPanel>
<TextBlock>outer</TextBlock>
<ContentControl local:RelativeFontSize.RelativeFontSize="2">
<StackPanel>
<TextBlock>inner</TextBlock>
<ContentControl local:RelativeFontSize.RelativeFontSize="2">
<StackPanel>
<TextBlock>innerest</TextBlock>
</StackPanel>
</ContentControl>
</StackPanel>
</ContentControl>
</StackPanel>
Which gives this:
And here's the code:
public static class RelativeFontSize
{
public static readonly DependencyProperty RelativeFontSizeProperty =
DependencyProperty.RegisterAttached("RelativeFontSize", typeof(Double), typeof(RelativeFontSize), new PropertyMetadata(1.0, HandlePropertyChanged));
public static Double GetRelativeFontSize(Control target)
=> (Double)target.GetValue(RelativeFontSizeProperty);
public static void SetRelativeFontSize(Control target, Double value)
=> target.SetValue(RelativeFontSizeProperty, value);
static Boolean isInTrickery = false;
public static void HandlePropertyChanged(Object target, DependencyPropertyChangedEventArgs args)
{
if (isInTrickery) return;
if (target is Control control)
{
isInTrickery = true;
try
{
control.SetValue(Control.FontSizeProperty, DependencyProperty.UnsetValue);
var unchangedFontSize = control.FontSize;
var value = (Double)args.NewValue;
control.FontSize = unchangedFontSize * value;
control.SetValue(Control.FontSizeProperty, unchangedFontSize * value);
}
finally
{
isInTrickery = false;
}
}
}
}
Related
A few short explanations before final question.
I have to clone different UserControls and Panels in my WPF app. I decided to use next approach:
xamlString = XamlWriter.Save(control.Content);
stringReader = new StringReader(xamlString);
xmlReader = XmlReader.Create(stringReader);
restoredVisual = (Visual)XamlReader.Load(xmlReader);
Also I have next class:
public class UnitLabel : Label
{
public string Unit
{
get { return (string )GetValue(UnitProperty); }
set { SetValue(UnitProperty, value); }
}
public static readonly DependencyProperty UnitProperty = DependencyProperty.Register("Unit", typeof(string), typeof(UnitLabel), new PropertyMetadata(""));
}
And template for this class
<ControlTemplate x:Key="template" TargetType="local:UnitLabel">
<StackPanel Orientation="Horizontal">
<ContentPresenter />
<ContentPresenter Content="{TemplateBinding Unit}" />
</StackPanel>
</ControlTemplate>
Question: Unit string is not visible after deserialization but property Unit has correct value. Do you have any ideas how to fix the issue?
I have found the reason and understood that my question is really stupid. Controls lose thier style and templates after deserialization. I can set style and it solves my problem.
Controls lose their styles and templates after deserialization. I can set style and it solves my problem.
I am new to WPF(4.0) and I am trying to make a simple form with some TEXTBOX and a SUBMIT BUTTON.
when user click on the submit Button and the program checks if all Textboxs filled, if not, the unfilled Textbox will surrounded by a "Red Border".
<StackPanel>
<Border Padding>
<StackPanel Orientation="Horizontal">
<TextBox Name="name_textbox"/>
</StackPanel>
</Border>
<Border>
<StackPanel>
<Button HorizontalAlignment="Center" Margin="0">Submit</Button>
</StackPanel>
</Border>
</StackPanel>
I read and I am trying to understand the following as well as some other documents and stack overflow posts and I found there are lots of things and terms that i could not understand.
https://www.codeproject.com/Articles/15239/Validation-in-Windows-Presentation-Foundation#welcome
https://www.codeproject.com/Articles/140620/WPF-Tutorial-Dependency-Property
My QUESTION is:
I think there are something to do with data binding validation, and apart from that what else should I need to know?
or are there any good resources recommend or quick examples?
I am lost and hope someone could help, thanks!
This is part of a class that i write to check validation after an element losts focus.
add FocusAdvancement in your window and set ValidationOnLostFocus to true. and add your custom validation in textbox ValidationRules.
public static class FocusAdvancement
{
public static readonly DependencyProperty ValidationOnLostFocusProperty=
DependencyProperty.RegisterAttached ("ValidationOnLostFocus",typeof (bool),typeof (FocusAdvancement),new UIPropertyMetadata (OnValidationOnLostFocusPropertyChanged));
public static bool GetValidationOnLostFocusProperty(DependencyObject d)
{
return (bool)d.GetValue (ValidationOnLostFocusProperty);
}
public static void SetValidationOnLostFocusProperty(DependencyObject d,bool value)
{
d.SetValue (ValidationOnLostFocusProperty,value);
}
private static void OnValidationOnLostFocusPropertyChanged(DependencyObject d,DependencyPropertyChangedEventArgs e)
{
var element=(UIElement)d;
if (element==null)
return;
if ((bool)e.NewValue)
{
element.LostFocus+=LostFocus;
}
else
element.GotFocus-=LostFocus;
}
private static void LostFocus(object sender,RoutedEventArgs e)
{
var element=(UIElement)sender;
if (element!=null)
{
TextBox oTextBox=(TextBox)element;
oTextBox.GetBindingExpression (TextBox.TextProperty).UpdateSource ();
}
}
In button flyout I am using one usercontrol inside that I have textbox. when running the app the textbox is appearing as readonly, don't know why I am getting this issue. nowhere I am setting readonly.
<TextBox Margin="2" Height="32"
MaxHeight="60"
TextWrapping="Wrap"
HorizontalAlignment="Stretch"
TextAlignment="Left"
Text="ramesh"
Style="{x:Null}"/>
Figure out the issue it's because of anniversary update.
https://blogs.msdn.microsoft.com/wsdevsol/2016/09/14/combobox-from-an-appbarbutton-loses-mouse-input-on-1607/
I created attached property for solution given in above link. Below is the attached property
public class CompatExtensions
{
public static bool GetAllowFocusOnInteraction(DependencyObject obj)
{
return (bool)obj.GetValue(AllowFocusOnInteractionProperty);
}
public static void SetAllowFocusOnInteraction(DependencyObject obj, bool value)
{
obj.SetValue(AllowFocusOnInteractionProperty, value);
}
// Using a DependencyProperty as the backing store for AllowFocusOnInteraction.
// This enables animation, styling, binding, etc...
public static readonly DependencyProperty AllowFocusOnInteractionProperty =
DependencyProperty.RegisterAttached("AllowFocusOnInteraction",
typeof(bool),
typeof(CompatExtensions),
new PropertyMetadata(0, AllowFocusOnInteractionChanged));
private static bool allowFocusOnInteractionAvailable =
Windows.Foundation.Metadata.ApiInformation.IsPropertyPresent(
"Windows.UI.Xaml.FrameworkElement",
"AllowFocusOnInteraction");
private static void AllowFocusOnInteractionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (allowFocusOnInteractionAvailable)
{
var element = d as FrameworkElement;
if (element != null)
{
element.AllowFocusOnInteraction = (bool)e.NewValue;
}
}
}
}
And an example of it used:
<AppBarButton local:CompatExtensions.AllowFocusOnInteraction="True" Icon="Setting">
<AppBarButton.Flyout>
<Flyout>
<StackPanel Orientation="Vertical" >
<ComboBox>
<ComboBoxItem Content="Red" IsSelected="True" />
<ComboBoxItem Content="Green" />
<ComboBoxItem Content="Blue"/>
</ComboBox>
</StackPanel>
</Flyout>
</AppBarButton.Flyout>
</AppBarButton>
Difficult to be sure about any answer given how the few details have been provided but I once saw something similar due to sizing of the TextBox. The UWP text box has a "delete" button (a small cross) at the end of the box to delete the current content. When the TextBox was sized vertically, the delete button scaled to take up the entirety of the TextBox thereby making it look read only.
If you're facing a similar issue, try setting AcceptsReturn="True" and InputScope="Text" on the TextBox.
I have a Control that displays something (let's call it Display). In this control I have a class Camera that stores things like zoom, position and rotation.
I can change the zoom from an external control (let's call it ZoomBar).
Now I had the idea to connect all of them with a TwoWay-Binding like this:
ZoomBar.Value <--> Display.Zoom <--> Camera.Zoom
It should be like: ZoomBar value changes --> update Display.Zoom --> update Camera.Zoom. Display.Zoom does not really do something. It's only for exchange the data between Camera and ZoomBar.
But I get nothing. After a short check in the Camera:
public float Zoom
{
get { MessageBox.Show("Any calls here?"); return (float)GetValue(ZoomProperty); }
set { ... }
}
I get a massive amount of MessageBoxes. I guess there is something like loop in there. Like ZoomBar.Value --> Display.Zoom --> ZoomBar.Value --> ...
My question
Are the two-way bindings causing the problem and if it is the bindings, is there a XAML way to fix this?
XAML ZoomBar
<StatusBarItem Title="Zoom Bar" HorizontalAlignment="Right">
<Slider x:Name="uxInputZoom" Style="{DynamicResource ZoomSliderStyle}" Value="100" Maximum="500" Minimum="20" />
</StatusBarItem>
XAML Display
<Display x:Name="uxDisplay" Zoom="{Binding Value, Converter={StaticResource PercentToFractionConverter}, ElementName=uxInputZoom, Mode=TwoWay}" />
Code Display
public static readonly DependencyProperty ZoomProperty = DependencyProperty.Register("Zoom", typeof(float), typeof(Display), new FrameworkPropertyMetadata(1f));
public float Zoom
{
get { return (float)GetValue(ZoomProperty); }
set { SetValue(ZoomProperty, value); }
}
Camera _camera = new Camera();
//...
public Display()
{
Binding binding = new Binding("Zoom");
binding.Source = _camera;
binding.Mode = BindingMode.TwoWay;
BindingOperations.SetBinding(this, Display.ZoomProperty, binding);
InitializeComponent();
...
}
You certainly can data bind one property value to more than one UI control. Take this simple example which enables movements of the Slider to update the value in the TextBox, while also enabling values entered in the TextBox to update the Slider.Value property:
<StackPanel>
<Slider Value="{Binding Width2}" Minimum="0.0" Maximum="100.0" Margin="0,0,0,20" />
<TextBox Text="{Binding Width2, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
This will not cause any feedback loops as in your code, so I suspect that you have something else doing that.
I would like to bind directly to the Blocks property of a RichTextBox in my Xaml. This is not possible as the Blocks property is read only. I can bind directly to an individual run:
<RichTextBox x:Name="MyRichTextBox" FontSize="36" Margin="10" Foreground="White">
<Paragraph>
<Run Text="{Binding MyObject.Text}" Foreground="Yellow"/>
<Run Text="{Binding MyObject.Text}" Foreground="Cyan"/>
</Paragraph>
</RichTextBox>
I would like to do something like:
<RichTextBox x:Name="MyRichTextBox" Blocks="{Binding MyObject.RichTextBlocks}" FontSize="36" Margin="10" Foreground="White"/>
Particularly as I don't know in advance how many blocks will be returned from the binding object.
Is the correct way to achieve this to create an Attached Behaviour for the RichTextBox with a RichTextBlocks property that when being set enumerates through the blocks and calls RichTextBox.Blocks.Add() for each one?
I am new to C#, .NET and XAML so please excuse the elementary question and a simply explained answer would be greatly appreciated.
With the pointers from #Nogard and the other post, I created my own class with a Dependency Property called RichText. Have posted here in case it is of use to anyone else.
public class MyRichTextBox : RichTextBox
{
public static readonly DependencyProperty RichTextProperty = DependencyProperty.Register("RichText", typeof(Paragraph), typeof(MyRichTextBox), new PropertyMetadata(null, RichTextPropertyChanged));
public Paragraph RichText
{
get
{
return (Paragraph)GetValue(RichTextProperty);
}
set
{
SetValue(RichTextProperty, value);
}
}
private static void RichTextPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
MyRichTextBox richTextBox = (MyRichTextBox)dependencyObject;
Paragraph paragraph = (Paragraph)dependencyPropertyChangedEventArgs.NewValue;
// Remove any existing content from the text box
richTextBox.Blocks.Clear();
// Add the paragraph to the text box
richTextBox.Blocks.Add(paragraph);
}
}
}
and added this to my xaml...
<sub:MyRichTextBox x:Name="MyRichTextOverlay" RichText="{Binding CurrentOverlay.RichTextParagraph}" VerticalAlignment="Top" FontSize="36" Margin="10" Foreground="White" HorizontalAlignment="Center" TextWrapping="Wrap" TextAlignment="Center"/>