adsl club

Справочник

Форум

Программы

Фильмы

Ресурсы

Файлообмен

Хостинг

Ростелеком
C#. WPF. Как закрыть окно (форму) по клику на дочернем (с большой вложенностью потомков) элементе этого окна.
На страницу 1 2
Ответить на тему    Форум АДСЛ КлубаЦИФРОВОЙ ФЛЕЙМ :)ПРОГРАММИРОВАНИЕ
Автор Сообщение
AlexRock
Гуру
СообщениеДобавлено: Пн 14-12-09 : 18-09    Заголовок сообщения: C#. WPF. Как закрыть окно (форму) по клику на дочернем (с большой вложенностью потомков) элементе этого окна. Ответить с цитатой

Заголовок темы - не вопрос. Вопрос в том, как сделать это с меньшими затратами, чем вариант, представленный ниже.

Динамически создаётся дочернее окно из родительского и в нём создаётся куча элементов с большой вложенностью по наследованию. К последнему элементу приделывается обработчик события нажатия кнопки мыши (infoDoc_MouseDown), по которому должно закрыться ЭТО ДОЧЕРНЕЕ окно, А НЕ РОДИТЕЛЬСКОЕ. Чтобы это сделать, мне пришлось подниматься по иерархии наследования и писать длиннющую строку с кучей приведений типов. Можно ли добиться того же, но без такой длинной строки, как указано в обработчике infoDoc_MouseDown?

Сразу говорю, что если в обработчике просто написать Close(), то закроется родительское окно, а если попытаться обратиться по имени дочернего окна - ДочернееОкно.Close() - то обработчик не знает о существовании дочернего окна и компилятор выдаёт ошибку. Хотя второй вариант был бы самым лучшим.

Код:
// В родительском окне кликаем по кнопке и всплывает новое, дочернее, окно.
void buttonClick(object sender, RoutedEventArgs e)
{
    // Создаём окно и несколько элементов.
    Window infoWindow = new Window();
    StackPanel panel = new StackPanel();
    FlowDocumentScrollViewer FDR = new FlowDocumentScrollViewer();
    FlowDocument infoDoc = new FlowDocument();

    // Прикрепляем обработчик к последнему элементу.
    infoDoc.MouseDown += new MouseButtonEventHandler(infoDoc_MouseDown);

    // Вкладываем элементы друг в друга. При этом элемент, для события которого назначен обработчик, оказывается в самом низу иерархии наследования.
    FDR.Document = infoDoc;
    panel.Children.Add(FDR);
    infoWindow.Content = panel;

    // Показываем окно в модальном виде.
    infoWindow.ShowDialog();
}


// Описание обработчика/
void infoDoc_MouseDown(object sender, RoutedEventArgs e)
{
   // Поднимаемся вверх по иерархии наследования, начиная от того, кто послал событие - sender, - пока не доберёмся до окна, чтобы закрыть его.
    ((Window)((StackPanel)((FlowDocumentScrollViewer)((FlowDocument)sender).Parent).Parent).Parent).Close();

    // Close() нельзя - закроется родительское окно.
    // infoWindow.Close() нельзя - этот обработчик не знает о существовании infoWindow.
}




Вот в цветном виде (лучше виден синтаксис):

 Наверх
Посмотреть профиль / Отправить личное сообщение Отправить личное сообщение  
ДобрыйФей
Мечтатель
Предупреждений : 5
СообщениеДобавлено: Пн 14-12-09 : 19-54    Заголовок сообщения: Ответить с цитатой

AlexRock писал(а):
Динамически создаётся дочернее окно из родительского и в нём создаётся куча элементов с большой вложенностью по наследованию. К последнему элементу приделывается обработчик события нажатия кнопки мыши (infoDoc_MouseDown), по которому должно закрыться ЭТО ДОЧЕРНЕЕ окно, А НЕ РОДИТЕЛЬСКОЕ. Чтобы это сделать, мне пришлось подниматься по иерархии наследования и писать длиннющую строку с кучей приведений типов. Можно ли добиться того же, но без такой длинной строки, как указано в обработчике infoDoc_MouseDown?

А если не делать большую вложенность и поставить кнопку в дочернее окно? Каким-нибудь образом.
 Наверх
Посмотреть профиль / Отправить личное сообщение Отправить личное сообщение  
ultrancux
Продвинутый форумчанин
СообщениеДобавлено: Пн 14-12-09 : 20-26    Заголовок сообщения: Ответить с цитатой

чет нифига ваще не понял help me

но видимо:

Код:

namespace _main
{
  form _child=new form();
  if(_child.ShowDialog()==DialogResult.OK)
  {
      _child.close(); 
  }
}
namespace _child
{
   private void mouseclick(Sender s,event e)
   {
       this.DialogResult=DialogResult.OK
   }
}
 Наверх
Посмотреть профиль / Отправить личное сообщение Отправить личное сообщение  
AlexRock
Гуру
СообщениеДобавлено: Пн 14-12-09 : 21-10    Заголовок сообщения: Ответить с цитатой

ДобрыйФей писал(а):
А если не делать большую вложенность и поставить кнопку в дочернее окно? Каким-нибудь образом.

Кнопка - не кошерно. Там по клику на кнопке небольшая справочная статья в модальном окне всплывает (это самое дочернее окно). Так нужно, чтобы это окно пропадало, когда по нему щёлкаешь (т. к. целиться мышью в спец. кнопку для закрытия напряжно для пользователя), а, поскольку всю рабочую область окна занимает FlowDocument, то удобнее повесить обработчик клика на него. Тогда получается, что нужно именно от него подниматься до окна, в котором сидит FlowDocument, чтобы до функции Close() этого окна добраться.



ultrancux
Не подходит, ибо событие клика (на самом деле - всего лишь опускания кнопки мыши - MouseDown) ловит FlowDocument, который всю рабочую область окна закрывает.

Я там что-то про пузырьковую всплывающую модель событий в WPF читал, но суть в том, что событие MouseDown ловит именно не окно (форма), а FlowDocument, т. к. он выше всех других контролов и контейнеров в окне находится, да ещё и всё окно закрывает как я уже писал, так что перехватить этот обработчик само окно (форма) не может.


Вот как дочернее окно выглядит - в крестик тыкать не кошерно, проще прямо в любое место окна долбануть:

 Наверх
Посмотреть профиль / Отправить личное сообщение Отправить личное сообщение  
ДобрыйФей
Мечтатель
Предупреждений : 5
СообщениеДобавлено: Вт 15-12-09 : 02-51    Заголовок сообщения: Ответить с цитатой

AlexRock
Тогда могу помочь только советом "гугл".
 Наверх
Посмотреть профиль / Отправить личное сообщение Отправить личное сообщение  
Richard Ferlow
Гуру
Предупреждений : 2
СообщениеДобавлено: Вт 15-12-09 : 02-54    Заголовок сообщения: Ответить с цитатой

AlexRock
а чего кнопка такая маленькая ? больше не сделать ? а если мне текст скопировать захочется ? а то что случайно нажал кнопку а закрылось то, что долго искал ?
 Наверх
Посмотреть профиль / Отправить личное сообщение Отправить личное сообщение   Номер ICQ
ДобрыйФей
Мечтатель
Предупреждений : 5
СообщениеДобавлено: Вт 15-12-09 : 02-57    Заголовок сообщения: Ответить с цитатой

AlexRock
Кстати, Ферлоу прав. Как скопировать текст, если при щелчке окно закрывается?
 Наверх
Посмотреть профиль / Отправить личное сообщение Отправить личное сообщение  
Richard Ferlow
Гуру
Предупреждений : 2
СообщениеДобавлено: Вт 15-12-09 : 03-10    Заголовок сообщения: Ответить с цитатой

а еще выравнивание текста по всей ширине - не ice
 Наверх
Посмотреть профиль / Отправить личное сообщение Отправить личное сообщение   Номер ICQ
ultrancux
Продвинутый форумчанин
СообщениеДобавлено: Вт 15-12-09 : 10-53    Заголовок сообщения: Ответить с цитатой

теперь ваще ничего не понял. напиши че надо иметь в конце, а не как это можно сделать
 Наверх
Посмотреть профиль / Отправить личное сообщение Отправить личное сообщение  
Aprelle
Гуру
СообщениеДобавлено: Вт 15-12-09 : 10-57    Заголовок сообщения: Ответить с цитатой

Может указатель окна при его создании запоминать или передавать, а потом по имеющемуся указателю закрывать?
 Наверх
Посмотреть профиль / Отправить личное сообщение Отправить личное сообщение  
AlexRock
Гуру
СообщениеДобавлено: Вт 15-12-09 : 13-05    Заголовок сообщения: Ответить с цитатой

ДобрыйФей писал(а):
AlexRock

Тогда могу помочь только советом "гугл".

Это я в первую очередь использую Smile , только что-то не шибко помог пока, да и не знаю я пока, как кратко сформулировать Гуглу этот вопрос (а иначе он воды надаёт).
Richard Ferlow писал(а):
а чего кнопка такая маленькая ? больше не сделать ? а если мне текст скопировать захочется ? а то что случайно нажал кнопку а закрылось то, что долго искал ?

Это инструментальное окно - WindowStyle.ToolWindow. Просто я хотел сделать вообще без рамки, но тогда его нельзя будет таскать. По сути, это должно быть что-то вроде всплывающей подсказки, поэтому копировать оттуда ничего не надо - это только для справки (см. пример в рис. ниже).

Однако, делать это в виде всплывающей подсказки некрасиво (там может быть до нескольких абзацев текста), поэтому я запихал всё в самый примитивный контейнер потокового документа, отрезав от него почти всю функциональность, кроме зуммирования и полосы прокрутки (не спрашивайте, почему я не поместил текст в TextBlock или ещё чего попроще - мне так захотелось Smile , сути это не меняет).

Далее, даже в стандартном окне крестик всё равно маленький - надо тянуться, поэтому проще "стукнуть" прямо по окну. А саму инфу из него можно получить в другом месте программы - там целая подробная статья генерируется со всей инфой какая нужна, а не только из этого окна.
Richard Ferlow писал(а):
а еще выравнивание текста по всей ширине - не ice

Вы флудерасты - я не спрашивал про вопросы юзабилити, тем более, что такое выравнивание здесь не сильно портит вид (если вообще портит). )))
Aprelle писал(а):
Может указатель окна при его создании запоминать или передавать, а потом по имеющемуся указателю закрывать?

В C# юзать указатели - не принято. )) По крайней мере, я ещё толком не разбирался с указателями в С#. Пока ищу способы обойтись без них.

Кстати, в Инете про объект Mutex какой-то иногда говорят, чтобы окна отслеживать - что-то мне кажется это тоже сложноватым. По крайней мере, даже моя длиннющая строка с кучей приведений попроще будет, наверное.
ultrancux писал(а):
теперь ваще ничего не понял. напиши че надо иметь в конце, а не как это можно сделать

Надо, чтобы окно закрывалось по щелчку по любому из его элементов - это вобщем. У меня в частности - по любой точке рабочей области окна (кроме рамки т. е.), т. к. FlowDocument занимает всю рабочую область окна. Но при этом FlowDocument не вложен непосредственно в окно, а содержится в серии вложенных контейнеров, самый "нижний" из которых уже содержится непосредственно в самом окне.

Как это можно сделать написал, чтобы то же самое не посоветовали. ))
 Наверх
Посмотреть профиль / Отправить личное сообщение Отправить личное сообщение  
AlexRock
Гуру
СообщениеДобавлено: Вт 15-12-09 : 13-17    Заголовок сообщения: Ответить с цитатой

AlexRock писал(а):
см. пример в рис. ниже

Блин, а в Яндексе можно копировать. (( ...Ну, вобщем, у меня нельзя будет. )) Потому что фича в том, чтобы закрывать окно именно по клику по любой его части - так удобнее. Хотя ещё подумаю над этим - может, сделаю по правой кнопке закрытие или по двойному щелчку. Вобщем, это к делу не относится - в любом случае событие надо будет "поднимать" (или "опускать" - в зависимости от того, что считать верхом, а что - низом) ручками, а я этого хочу избежать.
 Наверх
Посмотреть профиль / Отправить личное сообщение Отправить личное сообщение  
Wega
Гуру
СообщениеДобавлено: Вт 15-12-09 : 13-55    Заголовок сообщения: Ответить с цитатой

AlexRock
На вскидку.
1. Почему нельзя где-нибудь запомнить дочернее окно, которое надо закрыть?
хорошо, допустим нельзя (окон много, привязывать к объекту не красиво и т. д.) - не вдумывался;
2. Тогда используем нечто вида:
Код:
Object parent = current;
while(parent not instanceof Window) {
    parent = parent.getParent();
}
parent.close();

плюс проверки по необходимости.
3. По копированию и закрытию. Можно закрывать по событию клик_вверх при отсутствии выделения. Или сделать кнопку скопировать всё в буфер.
 Наверх
Посмотреть профиль / Отправить личное сообщение Отправить личное сообщение  
Aprelle
Гуру
СообщениеДобавлено: Вт 15-12-09 : 14-29    Заголовок сообщения: Ответить с цитатой

Я с C# пока не занимался особо, но наверняка там есть дерево иерархии, по которому можно вытянуть дочерние объекты.
Так что начиная от Application, или основного окна (смотри по дереву, куда оно там прикреплено) можно через .Items() или .getItem() или .getItembyId() сделать нечто типа Application.Windows.Items("infoWindow").Close();
 Наверх
Посмотреть профиль / Отправить личное сообщение Отправить личное сообщение  
Wega
Гуру
СообщениеДобавлено: Вт 15-12-09 : 14-34    Заголовок сообщения: Ответить с цитатой

Aprelle
А если таких окон 10? По названию не кошерно.
Ещё один вариант в дополнение к пункту 1:
можно общую карту использовать для соответствия панелька-окно.
 Наверх
Посмотреть профиль / Отправить личное сообщение Отправить личное сообщение  
Aprelle
Гуру
СообщениеДобавлено: Вт 15-12-09 : 14-41    Заголовок сообщения: Ответить с цитатой

Wega
Так эта конструкция 10 закрыть и не сможет, она в дереве только 1 выбирает. Если там более сложное дерево, то просто чуть более сложный выбор ветви и все.
Да и по коду видно, что infoWindow в ветви одно.
Это просто способ идти сверху вниз, а не снизу вверх, как пробовал автор, просивший предложить другие варианты.
 Наверх
Посмотреть профиль / Отправить личное сообщение Отправить личное сообщение  
Wega
Гуру
СообщениеДобавлено: Вт 15-12-09 : 14-59    Заголовок сообщения: Ответить с цитатой

Aprelle
Я про
Код:
Application.Windows.Items("infoWindow").Close();

У Application же может быть открыто 10 infoWindow? А закрыть надо одно по элементу которого сработало событие. Если первое предположение не верно, то тогда вариант должен быть рабочим.
Disclaimer: я совершенно не разбираюсь в дот нете.
 Наверх
Посмотреть профиль / Отправить личное сообщение Отправить личное сообщение  
AlexRock
Гуру
СообщениеДобавлено: Вт 15-12-09 : 14-59    Заголовок сообщения: Ответить с цитатой

Aprelle писал(а):
Я с C# пока не занимался особо, но наверняка там есть дерево иерархии, по которому можно вытянуть дочерние объекты.

Так что начиная от Application, или основного окна (смотри по дереву, куда оно там прикреплено) можно через .Items() или .getItem() или .getItembyId() сделать нечто типа Application.Windows.Items("infoWindow").Close();

Я примерно это и сделал, когда кучу приведений писал:
Код:
((Window)((StackPanel)((FlowDocumentScrollViewer)((FlowDocument)sender).Parent).Parent).Parent).Close();

Ещё раз говорю, что тут нет проблемы реализации, есть проблема, как сделать это не так заумно и более очевидно.
Wega писал(а):
А если таких окон 10? По названию не кошерно.

У меня делается без названия - достаточно иметь объект-отправитель "sеnder" и от него уже исходить.
Wega писал(а):
Ещё один вариант в дополнение к пункту 1:

можно общую карту использовать для соответствия панелька-окно.

Эммм... сдаётся мне, что это ещё сложнее, чем я в одну строку с приведениями типов написал. Всё должно быть ещё проще.


Я сейчас с маршрутизируемыми событиями разбираюсь - в них ключ. Только надо пока отследить, чтобы нужный мне объект (дочернее окно, а не все более нижние элементы) отработал это событие.
 Наверх
Посмотреть профиль / Отправить личное сообщение Отправить личное сообщение  
Aprelle
Гуру
СообщениеДобавлено: Вт 15-12-09 : 15-12    Заголовок сообщения: Ответить с цитатой

Цитата:
У Application же может быть открыто 10 infoWindow?

Я ж поясняю, что по дереву нужно смотреть, может через Application.Windows и будет 10, тогда вариант подправить нужно, а может как раз так как надо, или выбрать не Application.Windows, а типа Application.MainWindow.Panel[i].Items("infoWindow").Close();
Какой смысл судить о коде, если я этого дерева не вижу, видит только разработчик, ему виднее как делать, я просто предложил способ.

Цитата:
Я примерно это и сделал, когда кучу приведений писал

Цитата:
Ещё раз говорю, что тут нет проблемы реализации, есть проблема, как сделать это не так заумно и более очевидно.

Так я тебе и объясняю, что более очевидно делать по дереву не снизу вверх, а сверху вниз, собственно, обычно так и делают, разве что бывает выносят это в отдельную функцию.
 Наверх
Посмотреть профиль / Отправить личное сообщение Отправить личное сообщение  
Wega
Гуру
СообщениеДобавлено: Вт 15-12-09 : 15-27    Заголовок сообщения: Ответить с цитатой

Aprelle
Так а как выбрать нужную ветвь дерева (номер в массиве - i)? Нам в любом случае надо связать её с элементом (кнопкой), получившей событие.

А вообще код (точнее его структура) для такого продвинутого ООП-языка какой-то сильно кривой: обработчик открытия нового окна находится на том же уровне, что и внутренний обработчик закрытия этого окна.
 Наверх
Посмотреть профиль / Отправить личное сообщение Отправить личное сообщение  
Показать сообщения:   
Ответить на тему    Форум АДСЛ КлубаЦИФРОВОЙ ФЛЕЙМ :)ПРОГРАММИРОВАНИЕ Часовой пояс: GMT + 7
На страницу 1 2
Страница 1 из 2

 

 
Аватары: Вкл|Выкл   ЮзерИнфо: Вкл|Выкл   Подписи: Вкл|Выкл
Перейти:  
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете вкладывать файлы
Вы можете скачивать файлы