Question

I have a WPF application, and in this app, I have created a custom UserControl. This Control has the ability to load a defined Layout from XML. I would like to have a BOOL DependencyProperty on the UserControl which I can set true, and it would then load the desired layout. Addittionally I would like it to 'clear' this flag, by setting it back to False when completed. Essentially, I am trying to change the value of a Dependency Property inside the PropertyChanged handler.

This example will not update the property back to false at any time. In my actual application it works the very first time the trigger is set to True, but never again after that. I have a feeling it is because it is running the LoadTrigger = false NOT during the PropertyChanged.

Main Form

<Window x:Class="WPF_Test.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WPF_Test"
    Title="MainWindow" Height="350" Width="525">
<Grid>

    <CheckBox IsChecked="{Binding TriggerToLoad}"></CheckBox>

    <local:UC LoadTrigger="{Binding TriggerToLoad}"></local:UC>

    </Grid>
</Window>

Main Form - Code Behind

public partial class MainWindow : Window
{
    private TestViewModel VM;

    public MainWindow()
    {
        InitializeComponent();

        this.VM = new TestViewModel();

        this.DataContext = this.VM;

    }
}

User Control - Code Behind

public partial class UC : UserControl
{

    public static readonly DependencyProperty LoadTriggerProperty = DependencyProperty.Register("LoadTrigger", typeof(bool), typeof(UC), new  FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, LoadTriggerPropertyChanged));


    public bool LoadTrigger
    {
        get { return (bool)GetValue(LoadTriggerProperty); }
        set { this.SetValue(LoadTriggerProperty, value); }
    }

    private static void LoadTriggerPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
    {
        if ((bool)e.NewValue)
        {
            ((UC)source).LoadLayout();
        }
    }

    private void LoadLayout()
    {
        MessageBox.Show("Loading the layout now and then setting DependencyProperty back to false.");

        // TRIED THIS
        this.LoadTrigger = false;

        //TRIED THIS TOO
        //this.SetValue(LoadTriggerProperty, false);

        //TRIED THIS TOO
        //this.SetCurrentValue(LoadTriggerProperty, false);

        //TRIED THIS TOO
        //BindingOperations.GetBindingExpression(this, UC.LoadTriggerProperty).UpdateSource();
    }

    public UC()
    {
        InitializeComponent();
    }
}

ViewModel

 class TestViewModel : INotifyPropertyChanged
 {



    private bool triggerToLoad;

    public bool TriggerToLoad
    {
        get
        {
            return this.triggerToLoad;
        }

        set
        {
            if (this.triggerToLoad != value)
            {
                this.triggerToLoad = value;
                this.OnPropertyChanged("TriggerToLoad");
            }
        }
    }


    public TestViewModel()
    {
        this.TriggerToLoad = true;
    }



    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        if (!object.ReferenceEquals(this.PropertyChanged, null))
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

 }
Was it helpful?

Solution

Updating property in a handler seem to lead to undefined behaviour.

Defer layout loading (and flag update) in an async fashion:

private static void LoadTriggerPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
    if ((bool)e.NewValue)
    {
        //run "async" on the same UI thread:
        Dispatcher.BeginInvoke(((UC)source).LoadLayout);
    }
}

OTHER TIPS

you should look at DependencyObject.CoerceValue which is how you typically change dependency properties within propertychanged callbacks http://msdn.microsoft.com/en-us/library/system.windows.dependencyobject.coercevalue.aspx

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top