摘要:用相依性屬性 Attach 到視窗上,給 View-Model 關閉它
用相依性屬性 Attach 到視窗上,給 View-Model 關閉它
先假設寫一個用 RegisterAttach 註冊的相依性屬性,放到 Window 表頭上,這樣子 View-Model 就可以抓到這個 Window,在想關掉它的時候呼叫它的 Close().
但不巧的是,實際上 Run 的時候,執行完 Close() 它會出現錯誤:
「呼叫執行緒無法存取此物件,因為此物件屬於另一個執行緒。」
現在變成要用執行緒的方法解決這個問題。=>這是因為在 DependencyProperty中存的是Window,因為是static的,所以關閉的時候並沒有被release掉,才會造成這個問題。
只要把存Window Reference 改成存一個 Delegate 的話,就不會有這個問題了。
請看..
1、假設我的attach class叫MyAttachClass,在class中用DependencyProperty.RegisterAttached的方式註冊一個DependencyProperty:
namespace MyNameSpace
{
public class MyAttachClass
{
#region 相依性屬性 DependencyProperty: MyWindowActionProperty
public delegate void DCloseSubWindow();
public static DCloseSubWindow MyCloseSubWindow;
static void MyWindowActionChanged(DependencyObject Owner, DependencyPropertyChangedEventArgs e)
{
if (Owner != null)
{
Window win = Owner as Window;
if (win != null)
{
MyCloseSubWindow = new DCloseSubWindow(win.Close);
}
}
}
public static DependencyProperty MyWindowActionProperty = DependencyProperty.RegisterAttached(
"MyWindowAction",
typeof(string),
typeof(MyClass),
new FrameworkPropertyMetadata(
new PropertyChangedCallback(MyWindowActionChanged)));
public static void SetMyWindowAction(DependencyObject t, string value)
{
t.SetValue(MyWindowActionProperty, value);
}
public static string GetMyWindowAction(DependencyObject t)
{
return (string) t.GetValue(MyWindowActionProperty);
}
#endregion //相依性屬性 DependencyProperty: MyWindowActionProperty
}
...
}
2、在子window表頭上引用此物件,並加入DependencyProperty,指定什麼值並沒影響,因為我們只要Attach上去就行了。(子window的DataContent要指到View-Model)
<Window x:Class="MyNameSpace.MySubWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:a="clr-namespace:MyNameSpace;assembly=MyNameSpace"
a:MyAttachClass.MyWindowAction=""
>
<Grid>
<Button Command="{Binding CmdCloseMe}">Close Me!</Button>
</Grid>
</Window>
3、在View-Model中宣告ICommand,並在Execute中呼叫關閉子window的Delegate。
namespace MyNameSpace
{
...
public class MyClass
{
public RelayCommand CmdCloseMe { get; set; }
public MyClass()
{
CmdCloseMe = new RelayCommand(a => CloseMe());
}
void CloseMe()
{
//在這裡呼叫下面的delegate就可以關掉子window了
MyNameSpace.MyAttachClass.MyCloseSubWindow();
}
}
public class RelayCommand : ICommand
{
readonly Action