none
Вызвать нужное событие из динамически создаваемого TextBlock в другом окне из активного окна

    Вопрос

  • Нужно реализовать что-то в духе Toast Notification из Windows 8
    Есть главное окно приложения-MainWindow
    По некоторому событию генерируется событие ShowToast()

    Thread NotifyThread = new Thread(() =>
                {
                    NotificationWindow Toast = new NotificationWindow();
                    Toast.Show();
                    Toast.Closed += (sender2, e2) => { Toast.Dispatcher.InvokeShutdown(); };
                    System.Windows.Threading.Dispatcher.Run();
                }
                    );
                NotifyThread.SetApartmentState(ApartmentState.STA);
                NotifyThread.Start();

    Запускается новый WPF Window c нужными сообщениями, которые берутся из Properties.Settings.Default.ForNotification (массив string)

    for(int toast=0; toast!=Properties.Settings.Default.ForNotification.Count;toast++){
                    TextBlock toast= new TextBlock();
                    toast.Text = Properties.Settings.Default.ForNotification[toast];
                    ToastStack.Children.Add(toast);
                }
    //один раз получили уведомление и хватит, чистим массив
                Properties.Settings.Default.ForNotification.Clear();
    Как бы так сделать, чтобы щелкнув на toast открывался соответствующее toast сообщение в MainWindow

    Грубо говоря, в Toast окошке событие "У вас новое собщение от Валеры" (допустим eml100) щелкаю и открывается в MainWindow нужное мне eml100

    13 ноября 2014 г. 7:59

Ответы

  • Добрый день.

    Небольшой пример.

    1. В WPF приложение добавляю еще одну форму со следующими разметкой и кодом:

    <Window x:Class="WpfApplication6.SecondWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="SecondWindow" SizeToContent="WidthAndHeight">
        <StackPanel Orientation="Horizontal">
            <TextBox x:Name="tbInput" Width="150" Margin="5" />
            <Button Content="Отправить" Margin="5" Click="Button_Click" />
        </StackPanel>
    </Window>


    public partial class SecondWindow : Window
    {
        public SecondWindow()
        {
            InitializeComponent();
        }
    
        public event Action<string> TextEntered;
    
        protected void OnTextEntered(string p_text)
        {
            var handler = TextEntered;
            if (handler != null)
            {
                handler(p_text);
            }
        }
    
        public void ConfirmNumber(bool p_isConfirm)
        {
            if (p_isConfirm)
            {
                tbInput.Foreground = new SolidColorBrush(Colors.Green);
            }
            else
            {
                tbInput.Foreground = new SolidColorBrush(Colors.Red);
            }
        }
    
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            OnTextEntered(tbInput.Text);
        }
    }

    2. В код главной формы вношу изменения:

    public partial class MainWindow : Window
    {
        private SecondWindow _second;
    
        public MainWindow()
        {
            InitializeComponent();
            Loaded += MainWindow_Loaded;
        }
    
        void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            _second = new SecondWindow();
            _second.TextEntered += CheckText;
            _second.Show();
        }
    
        private void CheckText(string p_text)
        {
            int x;
            var result = false;
            if (int.TryParse(p_text, out x))
            {
                result = true;
            }
            _second.ConfirmNumber(result);
        }
    }

    3. Запускаю:

    Все, главная форма может влиять на дочернюю, а дочерняя передавать по своей
    инициативе данные главной для обработки.

    P.s. По шагам и с дополнительными комментариями можно посмотреть здесь.


    • Помечено в качестве ответа Evgeniy Nikulov 14 ноября 2014 г. 9:00
    14 ноября 2014 г. 7:22
    Отвечающий

Все ответы

  • Добрый день.

    Небольшой пример.

    1. В WPF приложение добавляю еще одну форму со следующими разметкой и кодом:

    <Window x:Class="WpfApplication6.SecondWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="SecondWindow" SizeToContent="WidthAndHeight">
        <StackPanel Orientation="Horizontal">
            <TextBox x:Name="tbInput" Width="150" Margin="5" />
            <Button Content="Отправить" Margin="5" Click="Button_Click" />
        </StackPanel>
    </Window>


    public partial class SecondWindow : Window
    {
        public SecondWindow()
        {
            InitializeComponent();
        }
    
        public event Action<string> TextEntered;
    
        protected void OnTextEntered(string p_text)
        {
            var handler = TextEntered;
            if (handler != null)
            {
                handler(p_text);
            }
        }
    
        public void ConfirmNumber(bool p_isConfirm)
        {
            if (p_isConfirm)
            {
                tbInput.Foreground = new SolidColorBrush(Colors.Green);
            }
            else
            {
                tbInput.Foreground = new SolidColorBrush(Colors.Red);
            }
        }
    
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            OnTextEntered(tbInput.Text);
        }
    }

    2. В код главной формы вношу изменения:

    public partial class MainWindow : Window
    {
        private SecondWindow _second;
    
        public MainWindow()
        {
            InitializeComponent();
            Loaded += MainWindow_Loaded;
        }
    
        void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            _second = new SecondWindow();
            _second.TextEntered += CheckText;
            _second.Show();
        }
    
        private void CheckText(string p_text)
        {
            int x;
            var result = false;
            if (int.TryParse(p_text, out x))
            {
                result = true;
            }
            _second.ConfirmNumber(result);
        }
    }

    3. Запускаю:

    Все, главная форма может влиять на дочернюю, а дочерняя передавать по своей
    инициативе данные главной для обработки.

    P.s. По шагам и с дополнительными комментариями можно посмотреть здесь.


    • Помечено в качестве ответа Evgeniy Nikulov 14 ноября 2014 г. 9:00
    14 ноября 2014 г. 7:22
    Отвечающий
  • Я реализовал немного по другому(коллеги подсказали)
    У второго окна создал свойство
    public MainWindow MainWindow { get; set; }
    В MainWindow
    Создаю тред
    Thread NotifyThread = new Thread(() => {
    NotificationWindow Toast = new NotificationWindow();
    Toast.Show();
    Toast.MainWindow = this;
    Toast.Closed += (sender2, e2) => { Toast.Dispatcher.InvokeShutdown(); };
    System.Windows.Threading.Dispatcher.Run();
    }
    );
    NotifyThread.SetApartmentState(ApartmentState.STA);
    NotifyThread.Start();


    Теперь во втором окне
    toasty.MouseLeftButtonDown += (obj, arg) => this.MainWindow.ShowToast(((System.Windows.Controls.TextBlock)obj).Text);
    Отрабатывается метод ShowToast главного окна
    public void ShowToast(String text) {
    this.Dispatcher.Invoke((Action)(() =>
    {
    tick.Text = text;
    }));
    }
    Но у этого подхода есть нарушение парадигмы ООП. Код получается непереносимый.
    14 ноября 2014 г. 12:43