Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF - Detect design mode in a Converter

I have a converter in which I want to be able to change the value to Visibility.Collapsed when in DesignMode. Right it is ignoring the GetIsInDesignMode.

Also, I am binding the VM via dependency injectio (prism)

Converter:

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {

        if (DesignerProperties.GetIsInDesignMode(new DependencyObject()))
            return Visibility.Collapsed;

        if (value != null && value is AllowedSourceCode)
        {
            var allowedSourceCode = (AllowedSourceCode)value;

            if (value == null)
                return Visibility.Visible;
            else if (allowedSourceCode.SupportedSourceCodes.Contains(allowedSourceCode.SelectedSourceCode))
            {
                return Visibility.Collapsed;
            }
            else
            return Visibility.Visible;

        }
        return Visibility.Collapsed;
    }

View:

        <Canvas Visibility="{Binding SupportedSourceCodes,Converter={StaticResource AllowedSourcesConverter}}" Background="Gray" Opacity="0.9"
            Grid.Row="0" Grid.Column="0" Grid.RowSpan="3" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Panel.ZIndex="5"  >

xaml.cs:

        public ACARSubLedgerUC(ACARSubLedgerVM vm)
    {
        InitializeComponent();
        DataContext = vm;
    }
like image 463
H20rider Avatar asked Oct 28 '15 21:10

H20rider


2 Answers

What you're doing should work.

I'm guessing you have a viewmodel behind your window and using the converter on a binding to that viewmodel. Please make sure you are setting your data context in XAML and not in code, because if you are setting it in code your converter will never hit in design mode.

<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:local="clr-namespace:WpfApp1"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        Title="MainWindow"
        Width="525"
        Height="350"
        mc:Ignorable="d">

    <Window.DataContext>
        <local:ViewModel />
    </Window.DataContext>

    ...

</Window>

This ensures bindings are updated at design time and hence your converter will be called.

like image 138
kkyr Avatar answered Nov 10 '22 16:11

kkyr


I wrote a markup extension that makes it way easier to muck around with design time bindings and property values without messing around with the code your view binds to or changing the actual runtime value of a property. The full write up is here: http://www.singulink.com/CodeIndex/post/wpf-visibility-binding-with-design-time-control

It works with visibility as well as most other properties. Usage looks like:

<Grid Visibility="{data:Value {Binding RootObject, Converter={StaticResource NullToVisibilityConverter}}, DesignValue=Visible}">
    <TextBlock Background="Red" Text="Testing visibility" />
</Grid>

The extension class:

public class ValueExtension : MarkupExtension
{
    public object DesignValue { get; set; } = DependencyProperty.UnsetValue;

    [ConstructorArgument("value")]
    public object Value { get; set; } = DependencyProperty.UnsetValue;

    public ValueExtension() { }

    public ValueExtension(object value)
    {
        Value = value;
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        var provideValueTarget = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
        var target = provideValueTarget.TargetObject as FrameworkElement;

        var value = DesignerProperties.GetIsInDesignMode(target) && DesignValue != DependencyProperty.UnsetValue ? DesignValue : Value;

        if (value == DependencyProperty.UnsetValue || value == null)
            return value;

        if (value is MarkupExtension)
        {
            return ((MarkupExtension)value).ProvideValue(serviceProvider);
        }

        var property = provideValueTarget.TargetProperty as DependencyProperty;

        if (property.PropertyType.IsInstanceOfType(value))
            return value;


        return TypeDescriptor.GetConverter(property.PropertyType).ConvertFrom(value);
    }
}
like image 20
Mike Marynowski Avatar answered Nov 10 '22 14:11

Mike Marynowski