Reputation: 1960
I have a DependencyProperty in my UserControl that uses a boolean to trigger a behaviour. In this case it is a UserControl designed to expose the feature of a SaveFileDialog and it uses a DialogVisible DependencyProperty. When the property is set to true I call the ShowDialog method on the SaveFileDialog in the Callback for the Property Change and then I try to set the DialogVisible property back to false, but this does not propagate back to the binding. I expect this is because I set the value inside the callback. Is there any way around this?
Code provided:
using System.Windows;
/// <summary>
/// Interaction logic for SaveFileDialog.xaml.
/// NOTE: Bindings for DialogVisible and FileName must
/// use TwoWay mode or dialog will not function as desired.
/// </summary>
public partial class SaveFileDialog
{
#region Depedancy Properties
public static readonly DependencyProperty FilterProperty = DependencyProperty.RegisterAttached(
"Filter",
typeof(string),
typeof(SaveFileDialog),
new PropertyMetadata(FilterProperty_Changed));
public static readonly DependencyProperty FileNameProperty = DependencyProperty.RegisterAttached(
"FileName",
typeof(string),
typeof(SaveFileDialog),
new PropertyMetadata(FileNameProperty_Changed));
public static readonly DependencyProperty InitialDirectoryProperty = DependencyProperty.RegisterAttached(
"InitialDirectory",
typeof(string),
typeof(SaveFileDialog),
new PropertyMetadata(InitialDirectoryProperty_Changed));
public static readonly DependencyProperty DefaultExtensionProperty = DependencyProperty.RegisterAttached(
"DefaultExtension",
typeof(string),
typeof(SaveFileDialog),
new PropertyMetadata(DefaultExtensionProperty_Changed));
public static readonly DependencyProperty DialogVisibleProperty = DependencyProperty.RegisterAttached(
"DialogVisible",
typeof(bool),
typeof(SaveFileDialog),
new PropertyMetadata(DialogVisibleProperty_Changed));
public string Filter
{
get { return (string)this.GetValue(FilterProperty); }
set { this.SetValue(FilterProperty, value); }
}
public string FileName
{
get { return (string)this.GetValue(FileNameProperty); }
set { this.SetValue(FileNameProperty, value); }
}
public string InitialDirectory
{
get { return (string)this.GetValue(InitialDirectoryProperty); }
set { this.SetValue(InitialDirectoryProperty, value); }
}
public string DefaultExtension
{
get { return (string)this.GetValue(DefaultExtensionProperty); }
set { this.SetValue(DefaultExtensionProperty, value); }
}
public bool DialogVisible
{
get { return (bool)this.GetValue(DialogVisibleProperty); }
set { this.SetValue(DialogVisibleProperty, value); }
}
private static void FilterProperty_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (SaveFileDialog)d;
control._dialog.Filter = (string)e.NewValue;
}
private static void FileNameProperty_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (SaveFileDialog)d;
control._dialog.FileName = (string)e.NewValue;
}
private static void InitialDirectoryProperty_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (SaveFileDialog)d;
control._dialog.InitialDirectory = (string)e.NewValue;
}
private static void DefaultExtensionProperty_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (SaveFileDialog)d;
control._dialog.DefaultExt = (string)e.NewValue;
}
private static void DialogVisibleProperty_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (SaveFileDialog)d;
if ((bool)e.NewValue)
{
control._dialog.ShowDialog();
control.DialogVisible = false;
control.FileName = control._dialog.FileName;
}
}
#endregion
private readonly Microsoft.Win32.SaveFileDialog _dialog = new Microsoft.Win32.SaveFileDialog();
public SaveFileDialog()
{
InitializeComponent();
}
}
Upvotes: 1
Views: 993
Reputation:
Typically, if you find yourself in a situation where your code is executing on the UI thread, but prior to a point where it makes sense, it is always possible to offload your work until some future point by using the UI thread's Dispatcher.
For example, if you have code running on startup, yet you expect that UI elements have been loaded and are ready for interaction, you can use the Dispatcher to execute your UI code later.
To do this, first you have to grab the UI Dispatcher. You can do this via Application.Current.Dispatcher
and offload execution of your update via BeginInvoke
, passing in the method or lambda you wish to invoke later.
This method has an overload that take a DispatcherPriority
enumeration. Use an appropriate priority. Typically, I use a priority of ContextIdle
, which executes after almost everything you need has completed.
Upvotes: 1