![](/img/trans.png)
[英]Specifically for a User Control, is there a place after the constructor, but before the Loaded event where you can access properties set in XAML?
[英]How can you access XAML-set properties of a UserControl during initialization?
我們正在編寫自定義UserControl(而不是無形控件),我們需要根據消費者在XAML中控制的屬性執行一些初始化。
現在在大多數情況下,您將使用Initialized事件(或OnInitialized覆蓋),因為在觸發時,已應用了所有XAML集屬性,但在UserControl的情況下,情況並非如此。 觸發Initialized事件時,所有屬性仍處於默認值。
我沒有注意到其他控件,只是UserControls,不同之處在於它們在構造函數中調用InitializeComponent(),所以作為測試,我評論說該行並運行代碼,果然,這次是在Initialized期間事件的性質設定。
以下是一些代碼和測試結果,證明了這一點......
在構造函數中調用InitializeComponent的結果:
(注意:值仍未設置)
TestValue (Pre-OnInitialized): Original Value
TestValue (Initialized Event): Original Value
TestValue (Post-OnInitialized): Original Value
InitializeComponent的結果已完全注釋掉:
(注意:雖然已設置值,但未加載控件,因為它需要InitializeComponent)
TestValue (Pre-OnInitialized): New Value!
TestValue (Initialized Event): New Value!
TestValue (Post-OnInitialized): New Value! // Event *was* called and the property has been changed
所有這些說,我可以使用什么來初始化我的控件基於XAML中的用戶設置屬性? (注意:加載已經太晚了,因為到那時控件應該已經初始化了。)
XAML片段
<local:TestControl TestValue="New Value!" />
TestControl.cs
public partial class TestControl : UserControl
{
public TestControl()
{
this.Initialized += TestControl_Initialized;
InitializeComponent();
}
protected override void OnInitialized(EventArgs e)
{
Console.WriteLine("TestValue (Pre-OnInitialized): " + TestValue);
base.OnInitialized(e);
Console.WriteLine("TestValue (Post-OnInitialized): " + TestValue);
}
void TestControl_Initialized(object sender, EventArgs e)
{
Console.WriteLine("TestValue (Initialized Event): " + TestValue);
}
public static readonly DependencyProperty TestValueProperty = DependencyProperty.Register(
"TestValue",
typeof(string),
typeof(TestControl),
new UIPropertyMetadata("Original Value"));
public string TestValue
{
get { return (string)GetValue(TestValueProperty); }
set { SetValue(TestValueProperty, value); }
}
}
Awesomesausage! 我想到了!
通常,當您收到Initialized
事件(或在OnInitialized
覆蓋內)時,您可以訪問XAML設置的屬性值。 但是, UserControl
類的工作方式略有不同,因為它們依賴於調用InitializeComponent
來水合UI並設置相關的成員變量等。
問題是調用是在構造函數中,而構造函數最終調用OnInitialized
(從而引發Initialized
事件)但是在應用XAML集屬性之前發生了這種情況,這意味着您還沒有訪問它們,我需要的。
有人可能會認為這對Loaded
事件很有用 - 根據這些屬性完成初始化 - 但是如果你在那里進行額外的初始化,那么如果他們訂閱了你的消費者就會產生潛在的競爭條件Loaded
事件並在你之前得到它,然后在他們的處理程序中嘗試訪問你的控件,他們將訪問一個未初始化的控件。
然后我發生了一些事情......正如我在上面所示,如果你從構造函數中刪除了InitializeComponent
調用,那么Initialized
事件現在可以正常工作了,但是當然你的UI還沒有被水合,因為你還沒有調用InitializeComponent
。
那么如果在調用base.OnInitialized
之前將調用移動到OnInitialized
覆蓋的開頭,從而在Initialized
事件被引發之前,會發生什么?
是的! 那很有效! :)
這樣你不僅擁有XAML集屬性,而且在任何人獲得Initialized
事件(更不用說Loaded
事件)之前你也會完全加載UI,這就是應該使用Initialized
事件的方式。
以下是修訂后的代碼......
public partial class TestControl : UserControl
{
protected override void OnInitialized(EventArgs e)
{
InitializeComponent();
base.OnInitialized(e);
}
public static readonly DependencyProperty TestValueProperty = DependencyProperty.Register(
"TestValue",
typeof(string),
typeof(TestControl),
new UIPropertyMetadata("Original Value"));
public string TestValue
{
get { return (string)GetValue(TestValueProperty); }
set { SetValue(TestValueProperty, value); }
}
}
InitializeComponent
調用之前你不能按名稱訪問組成控件,但這只是意味着你必須計划在InitializeComponent
和對base.OnInitialize
調用之間移動這種基於名稱的初始化,事情會起作用正好。 請在調用InitializeComponent之前注冊初始化事件。 只要調用EndInit或OnVisualParentChanges方法(即在InitializeComponent之后),就會引發此事件。
public TestControl()
{
this.Initialized += TestControl_Initialized;
InitializeComponent();
}
謝謝
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.