How to select date and time in WPF - c#

i'm looking for a control, that allow select both date and time. Default DatePicker doesn't allow it. But custom controls (like Extended WPFToolkit) are expensive, anothers are not free...

At the moment I posted it I came to a solution. So I leave it here if someone needs it:
<DatePicker Name="Picker">
<DatePicker.Resources>
<Style TargetType="DatePickerTextBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<TextBox Text="{Binding Path=SelectedDate, RelativeSource={RelativeSource AncestorType=DatePicker}, StringFormat={}{0:dd/MM/yyyy hh:mm:ss}}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DatePicker.Resources>
</DatePicker>

Related

Text of the textbox is always empty on a customized styling in wpf

Hey I'm designing a new style for a textbox in my WPF application using XAML codes. The textbox is a combination of textbox and textblock, I used the textblock to show name of the textbox when the text is null, and disappears when the text is filled, but there is a problem when I run the app and fill something in the textbox it seems that it's working properly but in the backend when I want to access the textbox Text it's null even though it's filled!!!!
Am I doing something wrong from the base or I missed something to do.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="{x:Type TextBox}"
x:Key="TextBoxTheme">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border CornerRadius="10"
Background="#353340"
Width="200"
Height="40">
<Grid>
<Rectangle StrokeThickness="1"/>
<TextBox Margin="1"
Text="{TemplateBinding Property=Text}"
BorderThickness="0"
Background="Transparent"
VerticalAlignment="Center"
Padding="5"
Foreground="#CFCFCF"
x:Name="textBox"/>
<TextBlock IsHitTestVisible="False"
Text="{TemplateBinding Name}"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10, 0, 0, 0"
FontSize="11"
Foreground="DarkGray">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding Text, ElementName=textBox}" Value="">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
<Setter Property="Visibility" Value="Hidden"/>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Instead of giving the TextBox an area to display its contents, you have overlapped it on top with another TextBox.
To display its content, the TextBox looks in the Template for ScrollViewer x:Name="PART_ContentHost".
Try a Template like this:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<Grid>
<TextBlock x:Name="PART_TextBlock" Text="{TemplateBinding Name}" Visibility="Collapsed"/>
<ScrollViewer x:Name="PART_ContentHost"
Focusable="false"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Text"
Value="{x:Static sys:String.Empty}">
<Setter TargetName="PART_TextBlock" Property="Visibility" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
Found this on the YouTube video comments where this question code comes from. In the template xaml file do the following:
Repalce This:
Text="{TemplateBinding Text}"
With This:
Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Text, UpdateSourceTrigger=PropertyChanged}"
I was able to capture text from the TextChanged event after this change.
If you check the documentation for TemplateBinding you'll see it's just syntactic sugar for a one-way RelativeSource binding to the templated parent, so all you need to do is change your TextBox binding to make it two-way:
Text="{Binding Path=Text, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
Also, I disagree with the comment above about this not being a good idea, one of the whole purposes of WPF's templating system is to make it possible to template existing controls e.g. for redistribution of libraries etc. That said, I don't think Name is the best property to use for your hint text, if for no other reason than the fact that it doesn't allow spaces. A much better solution would be to use an attached property. For a quick-and-dirty solution there's also the Tag property, which you're free to use for whatever you want.

How to write the date in DatePicker without the day name?

I'm using a DatePicker in WPF app and I'm trying to get the date with month name in arabic and without the name of day.
I'm following the documentation of DatePicker link
For example (image from the link of the documentation):
I would like to write the date without "Monday" and I prefer to get it in Arabic language,
Xaml Code:
<DatePicker SelectedDateFormat="Long" x:Name="EnteringDate" Foreground="White" Background="Transparent" Height="30" FlowDirection="RightToLeft" BorderBrush="White"/>
The desired output:
What I have tried , solution in StackOverflow but it does not work for me :
<DatePicker SelectedDateFormat="Long" x:Name="EnteringDate" Foreground="White" Background="Transparent" Height="30" FlowDirection="RightToLeft" BorderBrush="White"> <DatePicker.Resources>
<Style TargetType="{x:Type DatePickerTextBox}">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<TextBox x:Name="PART_TextBox"
Language="ar-EG"
Text="{Binding Path=SelectedDate, StringFormat='yyyy MMM dd',
RelativeSource={RelativeSource AncestorType={x:Type DatePicker}}}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DatePicker.Resources>
</DatePicker>
Try something like this, i.e. set the Language of the DatePicker to some arabic culture and then optionally change the format using an implicit DatePickerTextBox style:
<DatePicker Language="ar-EG">
<DatePicker.Resources>
<Style TargetType="{x:Type DatePickerTextBox}">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<TextBox x:Name="PART_TextBox" Text="{Binding Path=SelectedDate, StringFormat='yyyy MMM dd',
RelativeSource={RelativeSource AncestorType={x:Type DatePicker}}}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DatePicker.Resources>
</DatePicker>

TemplatedParent is null when used inside a ControlTemplate's DataTrigger

Consider this (edited-down) Style, designed for a Button whose Content is a String:
<Style x:Key="Test" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<StackPanel>
<TextBlock x:Name="text" Text="{TemplateBinding Content}" />
<TextBlock x:Name="demo" Text="{Binding RelativeSource={RelativeSource TemplatedParent}}" />
</StackPanel>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}">
<DataTrigger.Value>
<system:String>Test</system:String>
</DataTrigger.Value>
<Setter TargetName="test" Property="Foreground" Value="Red" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The intention in this example is to turn the button text red if it equals the word "Test"1. But it doesn't work, because the trigger's TemplatedParent binding resolves to null instead of to the Button the Style is applied to. However, the TextBlock named "demo" will have its Text set to "System.Windows.Controls.Button: [ButtonText]" as expected, which means TemplatedParent works correctly at that level. Why doesn't it work inside the DataTrigger?
1 I know there are other ways to achieve that, but I'm trying to understand why the binding doesn't work the way I expect it to.
TemplatedParent in your ControlTemplate.Triggers is not what you expect. Inside trigger it actually references Button.TemplatedParent. As such, it will only be non-null if your create that button inside template. You don't create button inside template, so it is null in your case. Now consider this xaml:
<Window.Resources>
<Style x:Key="Test"
TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<StackPanel>
<TextBlock x:Name="text"
Text="dummy" />
<TextBlock x:Name="demo"
Text="{Binding RelativeSource={RelativeSource TemplatedParent}}" />
</StackPanel>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}">
<DataTrigger.Value>
<system:String>Test</system:String>
</DataTrigger.Value>
<Setter TargetName="text"
Property="Foreground"
Value="Red" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="Test2" TargetType="ContentControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Button Style="{StaticResource Test}"></Button>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<!--<Button Content="Test" Style="{StaticResource Test}"/>-->
<ContentControl Style="{StaticResource Test2}" Content="Test" />
</Grid>
Here I retemplate ContentControl and inside template I use button with your template. If you run this code, you will see "dummy" text in red, because Button.TemplatedParent is now ContentControl, and it has it's Content equals "Test", which confirms what I said above.
Now back to your problem: just change RelativeSource TemplatedParent to RelativeSource Self (no need to change DataTrigger to Trigger) - this one would reference your Button.
I think it might be a similar issue in .NET Core WPF.
My DataTrigger was not firing with {Binding MyProp, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource Convert}}, but instead when I changed the RelativeSource to Self the binding started to work. I'm not sure whether it's a hack or a solution, but it worked.
Maybe it's worth mentioning that my template was based on MyView (see below) and I was binding to a DependencyProperty on MyView.
So my final code looked like this:
<ControlTemplate x:Key="Template" TargetType="{x:Type ns:MyView}">
<!-- Some template -->
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding MyProp, RelativeSource={RelativeSource Self}, Converter={StaticResource Convert}}" Value="True">
<Setter Property="Foreground" Value="Red"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
I'm not quite sure, but I think the trigger equals by referenc, because Content returns an Object. So it will never be true with your string defined within the trigger.

WPF: Styling ContentControl

I would like to create a style that could be applied to any ContentControl which would take the ToolTip and add an image to the ContentControl and apply the tool tip text from the object to the image. I have about a hundred of these that need to be done (in various projects) so being able to create a style would save a lot of typing.
What I am trying to recreate is this (ToolTip text is on the blue 'i' and not the 'Reload Employee Data':
which is accomplished via the following:
<StackPanel Orientation="Horizontal">
<CheckBox Content="Reload Employee Data"
IsChecked="{Binding AdjustmentSettings.ReloadEmployeeData}"
Grid.Row="0"
Grid.Column="0">
</CheckBox>
<Image Source="/DelphiaLibrary;Component/Resources/info.ico"
ToolTip="Check if you want to re-upload ..."/>
</StackPanel>
What I am trying to avoid is creating a new stack panel each time I want to add the blue 'i' with the tool tip text on the 'i' and not on the text of the object.
I was able to create the following that works for a Label:
<!-- Works for just Label -->
<Style x:Key="LabelToolTipStyle"
TargetType="{x:Type Label}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Label">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{TemplateBinding Content}" />
<Image Source="info.ico" ToolTip="{TemplateBinding ToolTip}"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And I can call this simply by adding the style to the label like so:
<Label Content="First Text" Style="{StaticResource LabelToolTipStyle}" ToolTip="Label with LabelToolTipStyle" />
I then tried to make this more generalized by creating a style targeting ContentControl but obviously doesn't work because this overrides the entire template (in the case of CheckBox control, the checkbox is missing):
<!-- Works on Label but not CheckBox -->
<Style x:Key="ContentToolTipStyle"
TargetType="{x:Type ContentControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{TemplateBinding Content}" />
<Image Source="info.ico" ToolTip="{TemplateBinding ToolTip}"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Is there a way that I could create a style for ContentControls that would allow me to ADD to the template without redefining the entire template? If it cannot be done to ContentControl I wouldn't be opposed to creating a separate style for each control type but would like to avoid redefining the entire template to do so.
You are almost there. You need to create a custom control template for a ContentControl:
<Style x:Key="ToolTipWrapper" TargetType="{x:Type ContentControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContentControl}">
<StackPanel Orientation="Horizontal">
<StackPanel.ToolTip>
<ToolTip Visibility="Hidden" />
</StackPanel.ToolTip>
<ContentPresenter />
<Image Source="info.ico" ToolTip="{TemplateBinding ToolTip}" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Then wrap your elements in a ContentControl and apply the style:
<ContentControl Style="{StaticResource ToolTipWrapper}" ToolTip="Hello world">
<CheckBox Content="I am a check box" />
</ContentControl>
What you can't do is to automatically apply the custom style to all "content" controls: you will always need the extra ContentControl wrapped around each element you want to style in this way.

How to read first 5 characters from string using StringFormat in Windows Phone XAML?

Basically in my Windows Phone application, i used to display the Name in the List through Binding. In this case, i want to restrict the name to display only the first 5 set of characters to avoid the unnecessary wrapping.
In my view, We can achieve this using the Converter option while binding the Name to the TextBox. But is there any other option to achieve this through XAML itself using StringFormat option while binding. Could you please anyone help me on this ?
<TextBox Text="{Binding Path=Name, StringFormat=??}" TextWrapping="NoWrap"/>
You could use the TextTrimming property of a TextBlock and create a style which contains a TextBlock inside your TextBox, like so:
Style 1
<!-- Trims text but shows all on-focus -->
<Style TargetType="TextBox" x:Key='TrimmingStyle1'>
<Style.Triggers>
<DataTrigger Binding="{Binding IsKeyboardFocused, RelativeSource={RelativeSource Self}}" Value="false">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Border BorderThickness='1' Background='#ffefefef' BorderBrush='LightBlue'>
<TextBlock Text="{TemplateBinding Text}" TextTrimming="None" Margin='4,1' />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
Style 2
<!-- Trims text always, non editable -->
<Style TargetType="TextBox" x:Key='TrimmingStyle2'>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Border BorderThickness='1' Background='#ffefefef' BorderBrush='LightBlue'>
<TextBlock Text="{TemplateBinding Text}" TextTrimming="None" Margin='4,1' />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Usage
<TextBox Style="{StaticResource TrimmingStyle1}" ... />
<TextBox Style="{StaticResource TrimmingStyle2}" ... />
Be sure to change the text bindings to match your application data. Also note that the trimming depends on the size of your textbox.
Source: Using a Style to Simulate TextTrimming on TextBox

Categories