Three material Design TextBoxes inside one MaterialDesignFloatingHintTexbox in WPF

Mesh Ka 345 Reputation points
2023-10-02T08:44:28.02+00:00

I have a MaterialDesignFloatingHintTextBox which displays a "Date of Birth" hint to my users when it is empty.

Screenshot 2023-10-01 001000

Here is what I want to implement: the TextBox to display three TextBoxes to the user when clicked in like this, so that my users enter the date part they know:

Screenshot 2023-10-01 000941

This is because my Users sometimes only know some parts of the date such as Year and Month Only, That was why i didn't use the DatePicker. The other thing that became hard to implement was the TextBox to display to the Use the date as following When it has a value:

WHEN THE USER PROVIDES A FULL DATE:

Screenshot 2023-10-01 002421

WHEN USER KNOWS MONTH AND YEAR ONLY:

Screenshot 2023-10-01 002429

WHEN THE USER PROVIDES ONLY THE YEAR:

Screenshot 2023-10-01 002436

Here is what I tried.

XAML:

<Window x:Class="DateTextBoxApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:DateTextBoxApp"
        xmlns:materialdesign="http://materialdesigninxaml.net/winfx/xaml/themes"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Dark.xaml"/>
                <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml"/>
                <ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.Green.xaml"/>
                <ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Accent/MaterialDesignColor.Lime.xaml"/>
            </ResourceDictionary.MergedDictionaries>
            <Style x:Key="NameTextBox" TargetType="TextBox" BasedOn="{StaticResource MaterialDesignFloatingHintTextBox}">
                <Setter Property="materialdesign:HintAssist.HintOpacity" Value="0.35"/>
                <Setter Property="materialdesign:ColorZoneAssist.Mode" Value="Dark"/>
                <Setter Property="materialdesign:HintAssist.HintOpacity" Value="0.35"/>
                <Setter Property="materialdesign:HintAssist.FontFamily" Value="Century Gothic"/>
                <Setter Property="Foreground" Value="AliceBlue"/>
                <Setter Property="FontSize" Value="20"/>
            </Style>
            <Style x:Key="DateTextBox" TargetType="TextBox" BasedOn="{StaticResource MaterialDesignFloatingHintTextBox}">
                <Setter Property="materialdesign:HintAssist.HintOpacity" Value="0.35"/>
                <Setter Property="materialdesign:ColorZoneAssist.Mode" Value="Dark"/>
                <Setter Property="materialdesign:HintAssist.HintOpacity" Value="0.35"/>
                <Setter Property="materialdesign:HintAssist.FontFamily" Value="Century Gothic"/>
                <Setter Property="Foreground" Value="AliceBlue"/>
                <Setter Property="FontSize" Value="20"/>
                <Style.Triggers>
                    <Trigger Property="IsKeyboardFocused" Value="True">
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="TextBox">
                                    <Grid>
                                        <Grid.ColumnDefinitions>
                                           <ColumnDefinition Width="*"/>
                                            <ColumnDefinition Width="*"/>
                                            <ColumnDefinition Width="*"/>
                                        </Grid.ColumnDefinitions>
                                        <TextBox x:Name="DayTextBox" Grid.Column="0" Text="{Binding Date, StringFormat='dd'}" TextAlignment="Center" Width="80"
                                                 materialdesign:HintAssist.Hint="Day" Style="{StaticResource MaterialDesignFloatingHintTextBox}"/>
                                        <TextBox x:Name="MonthTextBox"  Grid.Column="1" Text="{Binding Date, StringFormat='MM'}" TextAlignment="Center" Width="80"
                                                 materialdesign:HintAssist.Hint="Month" Style="{StaticResource MaterialDesignFloatingHintTextBox}"/>
                                        <TextBox x:Name="YearTextBox"  Grid.Column="2" Text="{Binding Date, StringFormat='yyyy'}" TextAlignment="Center"  Width="160"
                                                 materialdesign:HintAssist.Hint="Year" Style="{StaticResource MaterialDesignFloatingHintTextBox}"/>
                                    </Grid>
                                        <!-- Set the keyboard focus to the DayTextBox -->
                                        <ControlTemplate.Triggers>
                                            <Trigger Property="IsKeyboardFocused" Value="True">
                                                <Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=DayTextBox}" />
                                            </Trigger>
                                        </ControlTemplate.Triggers>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Trigger>
                    </Style.Triggers>
                </Style>
        </ResourceDictionary>
    </Window.Resources>

    <Grid>
        <Grid.Background>
            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                <GradientStop Color="#FF06013F" Offset="1"/>
                <GradientStop Color="#FF040F2E"/>
            </LinearGradientBrush>
        </Grid.Background>
        <StackPanel Margin="30" Orientation="Horizontal" Height="80">
            <TextBox Style="{StaticResource NameTextBox}" Width="100" materialdesign:HintAssist.Hint="FirstName" Margin="0 0 50 0"/>
            <TextBox Style="{StaticResource DateTextBox}" Text="{Binding DOB}" Width="200" materialdesign:HintAssist.Hint="Date Of Birth"/>
        </StackPanel>
    </Grid>
</Window>

But the problem is that the Textboxes don't accept Inputs, Why? and How can I achieve this?

Animation

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,686 questions
Visual Studio
Visual Studio
A family of Microsoft suites of integrated development tools for building applications for Windows, the web and mobile devices.
4,702 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,391 questions
XAML
XAML
A language based on Extensible Markup Language (XML) that enables developers to specify a hierarchy of objects with a set of properties and logic.
772 questions
{count} votes

Accepted answer
  1. gekka 7,091 Reputation points MVP
    2023-10-02T22:42:43.99+00:00
    <Window x:Class="WpfApp1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp1"
            xmlns:materialdesign="http://materialdesigninxaml.net/winfx/xaml/themes"
            mc:Ignorable="d"
            Title="MainWindow" Height="450" Width="800">
        <Window.Resources>
            <ResourceDictionary>
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Dark.xaml"/>
                    <ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml"/>
                    <ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.Green.xaml"/>
                    <ResourceDictionary Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Accent/MaterialDesignColor.Lime.xaml"/>
                </ResourceDictionary.MergedDictionaries>
                
                <Style x:Key="NameTextBox" TargetType="TextBox" BasedOn="{StaticResource MaterialDesignFloatingHintTextBox}">
                    <Setter Property="materialdesign:HintAssist.HintOpacity" Value="0.35"/>
                    <Setter Property="materialdesign:ColorZoneAssist.Mode" Value="Dark"/>
                    <Setter Property="materialdesign:HintAssist.HintOpacity" Value="0.35"/>
                    <Setter Property="materialdesign:HintAssist.FontFamily" Value="Century Gothic"/>
                    <Setter Property="Foreground" Value="AliceBlue"/>
                    <Setter Property="FontSize" Value="20"/>
                </Style>
    
    
                
                <ControlTemplate x:Key="DateTextBoxTemplate" TargetType="ContentControl">
                    <Grid DataContext="{TemplateBinding Content}" >
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="80"/>
                            <ColumnDefinition Width="80"/>
                            <ColumnDefinition Width="80"/>
                        </Grid.ColumnDefinitions>
    
                        <TextBox x:Name="dummyTextBox" Grid.Column="0"   TextAlignment="Center" HorizontalAlignment="Stretch" Grid.ColumnSpan="3"
                                 materialdesign:HintAssist.Hint="{Binding Path=(materialdesign:HintAssist.Hint),RelativeSource={RelativeSource Mode=TemplatedParent}}" 
                                 materialdesign:HintAssist.FloatingHintHorizontalAlignment="Right"
                                 materialdesign:HintAssist.FloatingOffset="0,-30"
                                 Style="{DynamicResource MaterialDesignFloatingHintTextBox}"
                                 IsTabStop="False" IsHitTestVisible="False"
                                 IsReadOnly="True" >
                        </TextBox>
    
                        <TextBox x:Name="DayTextBox" Grid.Column="0" Text="{Binding Day}" TextAlignment="Center" HorizontalAlignment="Stretch"
                                             materialdesign:HintAssist.Hint="Day" Style="{DynamicResource MaterialDesignFloatingHintTextBox}"
                                             TabIndex="0" Grid.ColumnSpan="3"
                                             Opacity="0.001"/>
    
                        <TextBox x:Name="MonthTextBox"  Grid.Column="1" Text="{Binding Month}" TextAlignment="Center" HorizontalAlignment="Stretch"
                                             materialdesign:HintAssist.Hint="Month" Style="{DynamicResource  MaterialDesignFloatingHintTextBox}"
                                             TabIndex="1" Visibility="Collapsed"/>
    
                        <TextBox x:Name="YearTextBox"  Grid.Column="2" Grid.Row="1" Text="{Binding Year}" TextAlignment="Center"  HorizontalAlignment="Stretch"
                                             materialdesign:HintAssist.Hint="Year" Style="{DynamicResource  MaterialDesignFloatingHintTextBox}"
                                             TabIndex="2" Visibility="Collapsed"/>
                    </Grid>
    
                    <ControlTemplate.Triggers>
    
                        <Trigger Property="IsKeyboardFocusWithin" Value="True">
                            <Setter TargetName="DayTextBox" Property="Opacity" Value="1"/>
                            <Setter TargetName="DayTextBox" Property="Grid.ColumnSpan" Value="1"/>
                            
    
                            <Setter TargetName="MonthTextBox" Property="Visibility" Value="Visible"/>
    
                            <Setter TargetName="YearTextBox" Property="Visibility" Value="Visible"/>
    
                            <Setter TargetName="dummyTextBox" Property="Text" Value=" "/>
                        </Trigger>
                        <Trigger Property="IsKeyboardFocusWithin" Value="false">
                            <Setter TargetName="dummyTextBox" Property="Text" Value="{Binding Path=FormatText}"/>
                        </Trigger>
    
                    </ControlTemplate.Triggers>
                </ControlTemplate>
                
                <Style x:Key="DateTextBox" TargetType="ContentControl" >
                    <Setter Property="materialdesign:HintAssist.HintOpacity" Value="0.35"/>
                    <Setter Property="materialdesign:ColorZoneAssist.Mode" Value="Dark"/>
                    <Setter Property="materialdesign:HintAssist.HintOpacity" Value="0.35"/>
                    <Setter Property="materialdesign:HintAssist.FontFamily" Value="Century Gothic"/>
                    <Setter Property="Foreground" Value="AliceBlue"/>
                    <Setter Property="FontSize" Value="20"/>
    
                    <Setter Property="IsTabStop" Value="False" />
    
                    <Setter Property="Template" Value="{StaticResource DateTextBoxTemplate}"/>
    
                </Style>
            </ResourceDictionary>
        </Window.Resources>
    
        <Grid>
            <Grid.Background>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FF06013F" Offset="1"/>
                    <GradientStop Color="#FF040F2E"/>
                </LinearGradientBrush>
            </Grid.Background>
            <StackPanel Margin="30" Orientation="Horizontal" Height="80">
                <TextBox Style="{StaticResource NameTextBox}" Width="100" materialdesign:HintAssist.Hint="FirstName" Margin="0 0 50 0"
                         VerticalAlignment="Bottom"/>
                <ContentControl Style="{StaticResource DateTextBox}" materialdesign:HintAssist.Hint="Date Of Birth"
                                VerticalAlignment="Bottom"
                                Content="{Binding Path=DOB}" />
            </StackPanel>
        </Grid>
    </Window>
    
    namespace WpfApp1
    {
        using System;
        using System.ComponentModel;
        using System.Globalization;
        using System.Windows;
    
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                this.DataContext = new TestModel();
            }
        }
    
        class TestModel : ModelBase
        {
            public DateVM DOB { get; } = new DateVM();
        }
    
        class DateVM : ModelBase
        {
            private string _Year;
            private string _Month;
            private string _Day;
    
            public string Year
            {
                get => _Year;
                set
                {
                    _Year = value;
                    OnChange();
                    OnPropertyChanged();
    
                }
            }
    
            public string Month
            {
                get => _Month;
                set
                {
                    _Month = value;
                    OnChange();
                    OnPropertyChanged();
                }
            }
    
            public string Day
            {
                get => _Day;
                set
                {
                    _Day = value;
                    OnChange();
                    OnPropertyChanged();
                }
            }
    
            private void OnChange()
            {
                bool has_y = !string.IsNullOrWhiteSpace(Year);
                bool has_m = !string.IsNullOrWhiteSpace(Month);
                bool has_d = !string.IsNullOrWhiteSpace(Day);
                if (has_y && has_m && has_d)
                {
                    FormatText = $"{ Day} / {Month} / {Year}";
                }
                else if (has_y && has_m && !has_d)
                {
                    FormatText = $"{Month} / {Year}";
                }
                else if (has_y && !has_m && !has_d)
                {
                    FormatText = $"{Year}";
                }
                else
                {
                    FormatText = null;
                }
            }
    
            public string FormatText
            {
                get => _FormatText;
                set
                {
                    _FormatText = value;
                    OnPropertyChanged();
                }
            }
            private string _FormatText;
        }
    
    
    
        class ModelBase : System.ComponentModel.INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
    
            protected void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string name = "")
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
            }
        }
       
    }
    
    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful