goul
goul

Reputation: 853

Control type switch based on data type being input or loaded

I have a field in my UI that can either take a date or a string.

I would like to switch on the type of control displayed depending on the data that is loaded in there or being input by the user.

In other words:

Can't find yet how to switch. Happy if you had some tip. Thank you!

Upvotes: 2

Views: 798

Answers (1)

Michał Turecki
Michał Turecki

Reputation: 3167

You would need to use templates depending on a type. To do this you would need either have 2 properties , one with type of a property and another with the actial object (both notifying INotifyPropertyChanged ).

    public object YourProperty
    {
        get
        {
            return yourProperty;
        }
        set
        {
            yourProperty = value;
            OnPropertyChanged();
            DateTime date;
            if(yourProperty is String && DateTime.TryParse((string) yourProperty, out date))
            {
                YourProperty = date;
            }
        }
    }
    private object yourProperty = string.Empty;
//public Type YourPropertyType { get; set; }

You also can create a converter which will return the type of a property, so you can get rid of additional property (commented out above):

public class TypeOfConverter : MarkupExtension, IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return (value == null) ? null : value.GetType();
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }
}

And finally bind a ContentControl to your property and select a template using the converter above:

            <ContentControl Content="{Binding YourProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
                <ContentControl.Resources>
                    <Style TargetType="ContentControl">
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding Path=YourProperty,Converter={flowMathTest:TypeOfConverter}}" Value="{x:Type system:DateTime}">
                                <Setter Property="ContentTemplate">
                                    <Setter.Value>
                                        <DataTemplate>
                                            <DatePicker SelectedDate="{Binding Content, RelativeSource={RelativeSource AncestorType=ContentControl}, UpdateSourceTrigger=PropertyChanged}"/>
                                        </DataTemplate>
                                    </Setter.Value>
                                </Setter>
                            </DataTrigger>
                            <DataTrigger Binding="{Binding Path=YourProperty,Converter={flowMathTest:TypeOfConverter}}" Value="{x:Type system:String}">
                                <Setter Property="ContentTemplate">
                                    <Setter.Value>
                                        <DataTemplate>
                                            <TextBox Text="{Binding Content, RelativeSource={RelativeSource AncestorType=ContentControl}, UpdateSourceTrigger=PropertyChanged}"/>
                                        </DataTemplate>
                                    </Setter.Value>
                                </Setter>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </ContentControl.Resources>
            </ContentControl>

Thant should do it.

EDIT: I did not read the second part so the switching between controls should happen as user writes.

What you can do in this case is to change bindings to Mode=TwoWay and UpdateSourceTrigger=PropertyChanged and handle detection of type in code.

By default set YourProperty to string.Empty. Then on every change check if the text entered is already date using DateTime.Parse. If it is, set YourProperty to this date.

So I updated the code above to reflect these changes.

Upvotes: 2

Related Questions