WPF實戰案例-MVVM模式下用附加屬性在Xaml中彈出窗體

嗯。。最近回家去了,2個月沒寫過代碼了,面試只能吹牛,基礎都忘了,今天回顧一下,分享一篇經過附加屬性去處理窗體彈出的狀況。面試

或許老司機已經想到了,經過設置附加屬性值,值變動的回調函數去處理窗體彈出,是的,很簡單,想法的問題。函數

public static readonly DependencyProperty IsModalProperty =
                    DependencyProperty.RegisterAttached("IsModal", typeof(bool), typeof(WindowHelper), new PropertyMetadata(true));

        public static readonly DependencyProperty OpenWindowTypeProperty =
                            DependencyProperty.RegisterAttached("OpenWindowType", typeof(Type), typeof(WindowHelper), new PropertyMetadata(null, OnOpenWindowTypeChanged));

        public static readonly DependencyProperty ParameterProperty =
            DependencyProperty.RegisterAttached("Parameter", typeof(object), typeof(WindowHelper), new PropertyMetadata(null));

三個附加屬性,是否模態窗口,窗口類型,傳遞到窗口的參數,事實上其實仍是經過反射處理的。ui

 

 private static void OnOpenWindowTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)

這是OpenWindowType屬性的變動回調函數spa

var type = GetOpenWindowType(d);
            if (type == null && type != typeof(Window))
            {
                return;
            }

            Window window = Activator.CreateInstance(type) as Window;

                     if (window == null)
                     {
                         return;
                     }
                 

                 if (GetParameter(d) != null)
                 {
                     window.Tag = GetParameter(d);
                 }

                 var isModel = GetIsModal(d);

                 window.Closed += (win, closeArgs) =>
                 {
                     
                     window = null;
                 };

                 if (isModel)
                 {
                     window.ShowDialog();
                 }
                 else
                 {
                     window.Show();
                 }

 

是吧,函數實現仍是很簡單的,看着明白了,那還少一點東西,什麼呢? 怎麼觸發這個變動函數!code

在說觸發的問題的時候,怎麼想一想怎麼使用它blog

attached:WindowHelper.IsModal="True"
                                    attached:WindowHelper.OpenWindowType="{x:Type local:Window1}"

是吧,添加引用而後設置屬性繼承

這個附加屬性咱們添加到哪裏呢?固然是哪裏用加哪裏了。 因此多是點擊button彈窗,也多是menuitem接口

因此,咱們要添加下面這段代碼,在屬性變動函數以前事件

dynamic control = null;
            switch (d.GetType().Name.ToString())
            {
                case "Button":
                    control = d as Button;
                    break;

                case "Hyperlink":
                    control = d as Hyperlink;
                    break;

                case "MenuItem":
                    control = d as MenuItem;
                    break;

                default:
                    return;
            }
var type = GetOpenWindowType(d);
            if (type == null && type != typeof(Window))
            {
                return;
            }

            Window window = null;
            var clickEventHandler = new RoutedEventHandler((s, arg) =>
             {
                 if (window == null)
                 {
                     window = Activator.CreateInstance(type) as Window;

                     if (window == null)
                     {
                         return;
                     }
                 }

                 if (GetParameter(d) != null)
                 {
                     window.Tag = GetParameter(d);
                 }

                 var isModel = GetIsModal(d);

                 window.Closed += (win, closeArgs) =>
                 {
                     
                     window = null;
                 };

                 if (isModel)
                 {
                     window.ShowDialog();
                 }
                 else
                 {
                     window.Show();
                 }
             });


            control.Click += clickEventHandler;

事實上,這個屬性變動只會有一次,就是初始化的時候,因此咱們在初始化的時候給按鈕註冊了事件,每次點擊的時候去彈出窗體,作到這一步其實其餘的就很好處理了,好比給vm傳遞參數,是否是用window.DataContext as VM,而後傳遞就能夠了?固然更好的方式是寫一個公共的接口,讓VM去繼承作處理。好比窗口關閉後須要調用某個函數作一些功能,是否是好實現多了,再加一個ICommand類型的附加屬性不就能夠了。回調函數

分享就到這裏,有更好的方案的同窗能夠加頁面下方的羣,歡迎討論

相關文章
相關標籤/搜索