Search code examples
wpfdata-bindinguser-controls

Hello, I need to set depedency property changing listener


I have a user control:

public partial class DialogControl : UserControl
{

    public BaseDialogInfo DialogInfo
    {
        get { return (BaseDialogInfo)GetValue(BaseDialogProperty); }
        set { SetValue(BaseDialogProperty, value); }
    }


    public static readonly DependencyProperty BaseDialogProperty=
            DependencyProperty.Register("DialogInfo", typeof(BaseDialogInfo), typeof(DialogControl), new UIPropertyMetadata(new BaseDialogInfo("", "", 0), new PropertyChangedCallback(OnDialogInfoPropertyChanged)));


    private static void OnDialogInfoPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        MessageBox.Show("");
        // Perform callback action.
    }

    public DialogControl()
    {
        InitializeComponent();
    }
}

And I have a main window:

C#:

public class DialogInfoContainer {
    public BaseDialogInfo info { get; set; }
}
public partial class MainWindow : Window
{
    public ObservableCollection<DialogInfoContainer> pathes;
    public MainWindow()
    {

        InitializeComponent();

        pathes = new ObservableCollection<DialogInfoContainer>() { new DialogInfoContainer() { info = new BaseDialogInfo("", "", 0) } };
        lb.ItemsSource = pathes;
    }
}

XAML:

<Grid>
    <ListBox x:Name="lb" Background="Transparent">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <local:DialogControl DialogInfo="{Binding Path=info}"></local:DialogControl>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Grid>

When I start the program, I get System.Windows.Markup.XamlParseException - Dispatcher processing has been suspended with inner InvalidOperationException - same description. But when I delete OnPropertyChangesListener from DependencyProperty I have no error. What have I done wrong? I have a lowlevel key hooks in my program, but I dont think they caused error.

Also, I want to know how I can bind element in collection because now I am binding custom class object with target object property.


Solution

  • welcome to stackoverflow. The InvalidOperationException is thrown because you do a MessageBox.Show(..) in the property changed handler. The reason for this exception is not that easy to explain. It has to do with reentrancy and the wpf message loop. Check out the answer to this question for more details.

    In short: you should avoid calling MessageBox.Show(..) in (User)Control code. If you still need to, you can work arround the problem by telling the dispatcher to show the messagebox when its done with layouting and altering the visual tree:

        private static void OnDialogInfoPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Application.Current.Dispatcher.BeginInvoke(new Action(() => {
                MessageBox.Show("Hello");
            }), DispatcherPriority.ApplicationIdle);
        }