2017-06-13 99 views
0

假设我们有一个依赖属性控制:Loaded事件和数据绑定在WPF

public class MyControl : ContentControl 
{ 

    static MyControl() 
    { 
     DefaultStyleKeyProperty.OverrideMetadata(typeof(MyControl), new FrameworkPropertyMetadata(typeof(MyControl))); 
    } 


    void DoSomething(object sender, RoutedEventArgs e) 
    { 
     //... 

    } 

    public MyControl() 
    {   
     this.Loaded += DoSomething; 
    } 

    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
     "Value", typeof(string), typeof(MyControl), 
     new FrameworkPropertyMetadata(default(string), 
      FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | FrameworkPropertyMetadataOptions.Journal, OnValueChanged)); 


    private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     //some actions    
    } 

    public string Value 
    { 
     get { return (string)GetValue(MyControl.ValueProperty); } 
     set { SetValue(MyControl.ValueProperty, value); } 
    }} 

而且在某处XAML我们绑定ValueProperty一些视图模型的某些属性瓦尔。

我的问题是,在Loaded事件被触发的时刻,MyControl.Value的值是否已经被设置为Val的值呢?那么,我是否能够在DoSomething方法中使用Val,并在MyControl被加载时执行?

非常感谢您提供任何答案。

+3

试试它会不会更容易? ;) –

+0

我试过了,并没有得到什么错误,在某些情况下它有效(值被设置),在其他情况下它没有,我不明白它依赖于什么,或者我错过了某些东西,所以我决定询问是否有任何定义的行为以及它依赖于什么。 –

+0

请不要吝啬,我只是问,我花了整整一天的时间来试图弄清楚这个问题并调试 –

回答

1
public class MyControl : ContentControl 
{ 
    public MyControl() 
    {   
     this.Loaded += (s,e) => DoSomething(); 
    } 

    private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     var c = (MyControl)d; 
     if (c.IsLoaded) 
      c.DoSomething();    
    } 

    // this will be called only if the control is loaded 
    private void DoSomething() 
    { 
     var value = Value; 
     if (value == null) 
     { 
      ... 
     } else if (value == string.Empty) 
     { 
      ... 
     } else 
     { 
     } 
    } 

    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
     "Value", typeof(string), typeof(MyControl), 
     new FrameworkPropertyMetadata(default(string), 
      FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | FrameworkPropertyMetadataOptions.Journal, OnValueChanged)); 

    public string Value 
    { 
     get { return (string)GetValue(MyControl.ValueProperty); } 
     set { SetValue(MyControl.ValueProperty, value); } 
    } 

    static MyControl() 
    { 
     DefaultStyleKeyProperty.OverrideMetadata(typeof(MyControl), new FrameworkPropertyMetadata(typeof(MyControl))); 
    } 

} 
+0

感谢您的回答,我只需要执行一些数据验证,以便在决定在控件加载时向用户显示什么之前执行某些操作,所以我需要的恰恰是显示控件之前的那一刻,但所有的属性都已经设置好了......我想可能是在Loaded事件之后。 –

1

我的问题是,在当Loaded事件被触发的瞬间,将MyControl.Value的价值已经被设置为val的值有或没有?

你不能依赖这个。 Loaded事件不是“数据绑定已完成”事件。此外,依赖项属性的值可以随时更改,处理Value属性的任何更改的地方位于OnValueChanged回调中。你可以检查是否控制已在回调被加载,如果你想:

private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
{ 
    MyControl ctrl = d as MyControl; 
    if (ctrl.IsLoaded) 
    { 
     //... 
    } 
} 

的一点是,你不应该在Loaded执行在你的依赖属性的值在回调依赖任何行动,事件处理器。

+0

是的,我理解你的观点。在我的情况下,数据从ViewModel加载,并检查其有效性,如果数据无效,则需要执行其他操作。因此,我需要定义一个适当时机,以便检查控件的所有属性,以便检查它,我认为当控件加载时,即属性已经设置的时间,因为文档说当加载被解雇了,所有的绑定都完成了(但是没有说关于他们被设置)...所以现在,Loaded不能被依赖,我正在以另一种方式实现这个 –

+1

你可以在每个依赖项中设置一个布尔标志属性回调,然后在设置所有标志后调用“完成”方法或其他东西。 – mm8

+0

是的,谢谢,我一直在想这样的事情...... –