工程中常常设计子窗口放在主窗口的指定位置,如图所示。测试窗口是红色,在主窗口的黑色区域(用了一个控件定位,比如Canvas等)。将位置设置好之后,相安无事。
但是将主窗口移动时,子窗口并没有跟着移动,出现如下情况,这并不是设计中期望的。
为了解决这个问题,采用子窗口控件位置绑定的办法。
主窗口中继承INotifyPropertyChanged接口,并定义2个属性性变量分别表示LeftSubWnd和TopSubWnd。
增加CompositionTarget.Rendering += new EventHandler(WindowPositionChange);来捕捉窗口位置发生的变化,并在相应的回调函数中修改属性变量的值,于是通过双向绑定的控件位置就自然发生变化,达到和主窗口跟随的效果。
代码如下
namespace TestMove { /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window, INotifyPropertyChanged { TestWnd mTestWnd = new TestWnd(); Window1 mWindow1 = new Window1(); //增加属性,子窗口的位置Left private double _leftSubWnd =0; public double LeftSubWnd { get { return _leftSubWnd; } set { if (_leftSubWnd != value) { _leftSubWnd = value; OnPropertyChanged("LeftSubWnd"); } } } //增加属性,子窗口的位置Top private double _topSubWnd = 0; public double TopSubWnd { get { return _topSubWnd; } set { if (_topSubWnd != value) { _topSubWnd = value; OnPropertyChanged("TopSubWnd"); } } } //重写属性改变 public event PropertyChangedEventHandler PropertyChanged; public virtual void OnPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } //初始化 public MainWindow() { InitializeComponent(); CompositionTarget.Rendering += new EventHandler(WindowPositionChange); } //位置发生变化 void WindowPositionChange(object sender, EventArgs e) { Point temPoint = canvas1.PointToScreen(new Point(0, 0)); mTestWnd.Owner = this; LeftSubWnd = temPoint.X; TopSubWnd = temPoint.Y; } //设置绑定 private void Window_Loaded(object sender, RoutedEventArgs e) { Binding temBindg = new Binding(); temBindg.Source = this; temBindg.Mode = BindingMode.TwoWay; temBindg.Path = new PropertyPath("LeftSubWnd"); mTestWnd.SetBinding(Window.LeftProperty, temBindg); mWindow1.SetBinding(Window.LeftProperty, temBindg); Binding temBindg2 = new Binding(); temBindg2.Source = this; temBindg2.Mode = BindingMode.TwoWay; temBindg2.Path = new PropertyPath("TopSubWnd"); mTestWnd.SetBinding(Window.TopProperty, temBindg2); mWindow1.SetBinding(Window.TopProperty, temBindg2); mTestWnd.Owner = this; mWindow1.Owner = this; mTestWnd.Show(); } private void button1_Click(object sender, RoutedEventArgs e) { mWindow1.Show(); mTestWnd.Hide(); } private void button2_Click(object sender, RoutedEventArgs e) { mTestWnd.Show(); mWindow1.Hide(); } } }