工程中常常设计子窗口放在主窗口的指定位置,如图所示。测试窗口是红色,在主窗口的黑色区域(用了一个控件定位,比如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();
}
}
}