вторник, 7 февраля 2012 г.

Изменение положения ChildWindow после его показа

В Silverlight есть замечательный класс ChildWindow, основная проблема с этим классом заключается в том, что это ни разу не Window. У него нет свойств Left, Top или X, Y... Это вообще Grid, который кладется в Z-буфер самым верхним, и закрывает доступ ко всему, что ниже, а потом уже рисуется контрол, который похож на окно. В чем проблема и как решать подкатом.
Сначала о проблеме. У нас написан универсальный метод который позволяет показать произвольный компонент в "модальном окне", причем размеры окна подстраиваются под под размеры компонента. Окно показывает кнопки принять/отмена реализует сервис по применению биндинга в переданном компоненте по кнопке принять и т.д. Проблема возникает когда компонент меняет свои размеры после того, как был показан. Окно расширяется, а левый верхний угол остается на месте.
До изменения размера:

После изменения размера:

Радостной новостью оказалось, что в ChildWindow мы помещаем Grid, у которого есть событие изменения размера. Собственно на него и приходиться подписать вот такой обработчик:

public static void ShowModal(FrameworkElement p_controlForShow, Action<bool> p_closeAction, ShowModalButton p_buttons = ShowModalButton.ApplyCancel, string p_closeButton = "Отмена"string p_applyButton = "Принять"string p_Title = "")
{
 // Технология следующая, показываем Grid, 
 // в него контрол который передал пользователь, плюс кнопки принять и отмена
 // Если пользователь нажимает принять, то в контрол передаем принять изменения
 ChildWindow ch = new ChildWindow();
 ch.Title = p_Title;
 Grid modalGrid = new Grid();
 
 #region Настройка Grid
 modalGrid.SizeChanged += (s, e) => { modalGrid_SizeChanged(ch, e); };
        ...

Собственно обработчик изменения размера нашего грида:

static void modalGrid_SizeChanged(object sender, SizeChangedEventArgs e)
{
 FrameworkElement ch = sender as FrameworkElement;
 if (ch != null)
 {
  double height = Application.Current.Host.Content.ActualHeight - 40 > 0 ? Application.Current.Host.Content.ActualHeight - 40 : 300;
  double width = Application.Current.Host.Content.ActualWidth - 40 > 0 ? Application.Current.Host.Content.ActualWidth - 40 : 450;
  if (width != 0 && height != 0)
  {
   Application.Current.RootVisual.Dispatcher.BeginInvoke
    (
    () =>
    {
     FrameworkElement root = (FrameworkElement)VisualTreeHelper.GetChild
         (сh, 0);
     FrameworkElement contentroot = root.FindName("ContentRoot")
         as FrameworkElement;
     double x = (Application.Current.Host.Content.ActualWidth - width) / 2;
     double y = (Application.Current.Host.Content.ActualHeight - height) / 2;
     if (contentroot != null)
     {
      TransformGroup group = contentroot.RenderTransform as TransformGroup;
      if (group != null)
      {
       TranslateTransform translateTransform = null;
       foreach (var transform in group.Children.OfType<TranslateTransform>())
       {
        translateTransform = transform;
       }
       if (translateTransform != null)
       {
        // reset transform
        translateTransform.X = 0.0;
        translateTransform.Y = 0.0;
       }
      }
     }
    }
    );
  }
 }
}

Правда жуть?

Комментариев нет:

Отправить комментарий