none
Реагирование на деиствие RRS feed

  • Вопрос

  • делаю приложение на Silverlight. Есть форма, на ней есть текстбокс - я в него ввожу даные, нажимаю на кнопку - появляется дочернее окно. На нем есть две кнопки - в зависимости от нажатия одной из них - должно происходить некое деиствие с этими данными. Как решить?
    19 февраля 2011 г. 11:43

Ответы

  • Если заменить на UserControl – на нем будет вполне конкретная кнопка “I Agree”, OnClick можно вытянуть в главное окно:
    1. В UserControl объявляешь свое событие OnAgree.
    2. В главном окне подписываешься на него.
    3. После регистрации показываешь User Control.
    4. По клику на “I Agree” в контроле получаешь OnClick.
    5. В OnClick вызываешь this.Agree(...)
    6. В главном окне вызывается LicenseControl_OnAgree, в котором отправляешь данные сервису.
     
    Или можно взять готовый пример с codeplex, по ссылке из моего ответа выше...

    My blog
    19 февраля 2011 г. 14:22
  • Вот простой пример, реализующий шаблон MVVM для привязки данных. В нем также используется вспомогательный класс Command, чтобы представление не было привязано к методам-обработчикам класса.

    Это самый правильный с точки зрения архитектуры вариант. Альтернативный простой вариант: сделать открытое свойство MyText класса MainWindow, в обработчиках нажатия на кнопку отображать дочернее окно, которому в конструкторе передавать ссылку на экземпляр MainWindow, а в обработчиках нажатия на кнопки дочернего окна изменять это свойство или даже вызывать метод обновления, который изменит его в элементе TextBox, но это создаст высокую связность классов и представлений, что впоследствии может привести к проблемам.

    Вот, собственно, сам пример:

    Новое приложение SilverlightApplication4.

    Файл MainPage.xaml:

     

    <UserControl x:Class="SilverlightApplication4.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Height="80">
      <StackPanel Orientation="Horizontal" Margin="20">
        <TextBox Text="{Binding MyText, Mode=TwoWay}" Width="200" />
        <Button Content="Button" Width="75" Command="{Binding ButtonCommand}" />
      </StackPanel>
    </UserControl>
    

     

    Файл MainPage.xaml.cs:

     

    using System;
    using System.ComponentModel;
    using System.Windows.Controls;
    using System.Windows.Input;
    
    namespace SilverlightApplication4
    {
      public partial class MainPage : UserControl, INotifyPropertyChanged
      {
        private string myText;
        private Command buttonCommand;
        private ChildWindow1 childWindow1;
    
        public MainPage()
        {
          InitializeComponent();
          DataContext = this;
          childWindow1 = new ChildWindow1();
          childWindow1.Button1Click += childWindow1_Button1Click;
          childWindow1.Button2Click += childWindow1_Button2Click;
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        public string MyText
        {
          get
          {
            return myText;
          }
          set
          {
            myText = value;
            OnPropertyChanged("MyText");
          }
        }
    
        public ICommand ButtonCommand
        {
          get
          {
            if (buttonCommand == null)
              buttonCommand = new Command
              (
                param => true,
                param =>
                {
                  ButtonClick();
                }
              );
            return buttonCommand;
          }
        }
    
        private void ButtonClick()
        {
          childWindow1.Show();
        }
    
        private void childWindow1_Button1Click(object sender, EventArgs e)
        {
          MyText += " Button 1 Clicked";
        }
    
        private void childWindow1_Button2Click(object sender, EventArgs e)
        {
          MyText += " Button 2 Clicked";
        }
    
        private void OnPropertyChanged(string propertyName)
        {
          if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
      }
    }
    
    

     

    Файл ChildWindow1.xaml:

     

    <controls:ChildWindow x:Class="SilverlightApplication4.ChildWindow1"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
          xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
          Width="200" Height="100" 
          Title="ChildWindow1">
      <StackPanel Orientation="Horizontal" Margin="20">
        <Button Content="Button1" Width="70" Command="{Binding Button1Command}" />
        <Button Content="Button2" Width="70" Command="{Binding Button2Command}" />
      </StackPanel>
    </controls:ChildWindow>
    

     

    Файл ChildWindow1.xaml.cs:

     

    using System;
    using System.Windows.Controls;
    using System.Windows.Input;
    
    namespace SilverlightApplication4
    {
      public partial class ChildWindow1 : ChildWindow
      {
        private Command button1Command;
        private Command button2Command;
    
        public ChildWindow1()
        {
          InitializeComponent();
          DataContext = this;
        }
    
        public event EventHandler Button1Click;
        public event EventHandler Button2Click;
    
        public ICommand Button1Command
        {
          get
          {
            if (button1Command == null)
              button1Command = new Command
              (
                param => true,
                param =>
                {
                  OnButton1Click();
                  Close();
                }
              );
            return button1Command;
          }
        }
    
        public ICommand Button2Command
        {
          get
          {
            if (button2Command == null)
              button2Command = new Command
              (
                param => true,
                param =>
                {
                  OnButton2Click();
                  Close();
                }
              );
            return button2Command;
          }
        }
    
        private void OnButton1Click()
        {
          EventHandler handler = Button1Click;
          if (handler != null)
            handler(this, EventArgs.Empty);
        }
    
        private void OnButton2Click()
        {
          EventHandler handler = Button2Click;
          if (handler != null)
            handler(this, EventArgs.Empty);
        }
      }
    }
    
    

     

    Файл Command.cs:

     

    using System;
    using System.Windows.Input;
    
    namespace SilverlightApplication4
    {
      public class Command : ICommand
      {
        Predicate<Object> canExecute = null;
        Action<Object> executeAction = null;
    
        public Command(Predicate<Object> canExecute, Action<object> executeAction)
        {
          this.canExecute = canExecute;
          this.executeAction = executeAction;
        }
    
        public event EventHandler CanExecuteChanged;
    
        public bool CanExecute(object parameter)
        {
          if (canExecute != null)
            return canExecute(parameter);
          return true;
        }
    
        public void UpdateCanExecuteState()
        {
          if (CanExecuteChanged != null)
            CanExecuteChanged(this, new EventArgs());
        }
    
        public void Execute(object parameter)
        {
          if (executeAction != null)
            executeAction(parameter);
          UpdateCanExecuteState();
        }
    
      }
    }
    
    
    В зависимости от смысла операций с данными эти операции могут размещаться как в вызывающем класса (как в этом примере), так и в классе ChildWindow1.

     

    19 февраля 2011 г. 12:26

Все ответы

  • Нужно использовать привязку данных (databinding). Если нужно, могу сделать простой пример.
    19 февраля 2011 г. 11:48
  • ну сделайте, посмотрю..
    19 февраля 2011 г. 12:06
  • Вот простой пример, реализующий шаблон MVVM для привязки данных. В нем также используется вспомогательный класс Command, чтобы представление не было привязано к методам-обработчикам класса.

    Это самый правильный с точки зрения архитектуры вариант. Альтернативный простой вариант: сделать открытое свойство MyText класса MainWindow, в обработчиках нажатия на кнопку отображать дочернее окно, которому в конструкторе передавать ссылку на экземпляр MainWindow, а в обработчиках нажатия на кнопки дочернего окна изменять это свойство или даже вызывать метод обновления, который изменит его в элементе TextBox, но это создаст высокую связность классов и представлений, что впоследствии может привести к проблемам.

    Вот, собственно, сам пример:

    Новое приложение SilverlightApplication4.

    Файл MainPage.xaml:

     

    <UserControl x:Class="SilverlightApplication4.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Height="80">
      <StackPanel Orientation="Horizontal" Margin="20">
        <TextBox Text="{Binding MyText, Mode=TwoWay}" Width="200" />
        <Button Content="Button" Width="75" Command="{Binding ButtonCommand}" />
      </StackPanel>
    </UserControl>
    

     

    Файл MainPage.xaml.cs:

     

    using System;
    using System.ComponentModel;
    using System.Windows.Controls;
    using System.Windows.Input;
    
    namespace SilverlightApplication4
    {
      public partial class MainPage : UserControl, INotifyPropertyChanged
      {
        private string myText;
        private Command buttonCommand;
        private ChildWindow1 childWindow1;
    
        public MainPage()
        {
          InitializeComponent();
          DataContext = this;
          childWindow1 = new ChildWindow1();
          childWindow1.Button1Click += childWindow1_Button1Click;
          childWindow1.Button2Click += childWindow1_Button2Click;
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        public string MyText
        {
          get
          {
            return myText;
          }
          set
          {
            myText = value;
            OnPropertyChanged("MyText");
          }
        }
    
        public ICommand ButtonCommand
        {
          get
          {
            if (buttonCommand == null)
              buttonCommand = new Command
              (
                param => true,
                param =>
                {
                  ButtonClick();
                }
              );
            return buttonCommand;
          }
        }
    
        private void ButtonClick()
        {
          childWindow1.Show();
        }
    
        private void childWindow1_Button1Click(object sender, EventArgs e)
        {
          MyText += " Button 1 Clicked";
        }
    
        private void childWindow1_Button2Click(object sender, EventArgs e)
        {
          MyText += " Button 2 Clicked";
        }
    
        private void OnPropertyChanged(string propertyName)
        {
          if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
      }
    }
    
    

     

    Файл ChildWindow1.xaml:

     

    <controls:ChildWindow x:Class="SilverlightApplication4.ChildWindow1"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
          xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
          Width="200" Height="100" 
          Title="ChildWindow1">
      <StackPanel Orientation="Horizontal" Margin="20">
        <Button Content="Button1" Width="70" Command="{Binding Button1Command}" />
        <Button Content="Button2" Width="70" Command="{Binding Button2Command}" />
      </StackPanel>
    </controls:ChildWindow>
    

     

    Файл ChildWindow1.xaml.cs:

     

    using System;
    using System.Windows.Controls;
    using System.Windows.Input;
    
    namespace SilverlightApplication4
    {
      public partial class ChildWindow1 : ChildWindow
      {
        private Command button1Command;
        private Command button2Command;
    
        public ChildWindow1()
        {
          InitializeComponent();
          DataContext = this;
        }
    
        public event EventHandler Button1Click;
        public event EventHandler Button2Click;
    
        public ICommand Button1Command
        {
          get
          {
            if (button1Command == null)
              button1Command = new Command
              (
                param => true,
                param =>
                {
                  OnButton1Click();
                  Close();
                }
              );
            return button1Command;
          }
        }
    
        public ICommand Button2Command
        {
          get
          {
            if (button2Command == null)
              button2Command = new Command
              (
                param => true,
                param =>
                {
                  OnButton2Click();
                  Close();
                }
              );
            return button2Command;
          }
        }
    
        private void OnButton1Click()
        {
          EventHandler handler = Button1Click;
          if (handler != null)
            handler(this, EventArgs.Empty);
        }
    
        private void OnButton2Click()
        {
          EventHandler handler = Button2Click;
          if (handler != null)
            handler(this, EventArgs.Empty);
        }
      }
    }
    
    

     

    Файл Command.cs:

     

    using System;
    using System.Windows.Input;
    
    namespace SilverlightApplication4
    {
      public class Command : ICommand
      {
        Predicate<Object> canExecute = null;
        Action<Object> executeAction = null;
    
        public Command(Predicate<Object> canExecute, Action<object> executeAction)
        {
          this.canExecute = canExecute;
          this.executeAction = executeAction;
        }
    
        public event EventHandler CanExecuteChanged;
    
        public bool CanExecute(object parameter)
        {
          if (canExecute != null)
            return canExecute(parameter);
          return true;
        }
    
        public void UpdateCanExecuteState()
        {
          if (CanExecuteChanged != null)
            CanExecuteChanged(this, new EventArgs());
        }
    
        public void Execute(object parameter)
        {
          if (executeAction != null)
            executeAction(parameter);
          UpdateCanExecuteState();
        }
    
      }
    }
    
    
    В зависимости от смысла операций с данными эти операции могут размещаться как в вызывающем класса (как в этом примере), так и в классе ChildWindow1.

     

    19 февраля 2011 г. 12:26
  • Алексей, это немного не то что мне нужно. Короче есть форма - на ней есть тескбоксы, радиобатоны, и т.д. На форме есть кнопка - я на нее нажимаю - выполняется некий мой код, затем открывается дочернее окно, дальше в зависимости от нажатия на одну з кнопок код на моей первой форме выполняется дальше, тоисть надо как-нибудь остановить выполнение дальнейшего кода, пока пользователь не нажмет на одну с кнопок - тогда я смотрю как-то на какую именно кнопку он нажал и продолжаю выполнение некого кода.

    19 февраля 2011 г. 13:06
  • Обычное модальное окно не подойдет? http://slmodalwizard.codeplex.com/ , например.
    Или попробовать заменить отдельное окно на UserControl, вроде http://weblogs.asp.net/scottgu/pages/silverlight-tutorial-part-6-using-user-controls-to-implement-master-detail-scenarios.aspx

    My blog
    19 февраля 2011 г. 13:33
  • Я Вас понимаю: Вы хотите подвести выполнение программы под идеологию WinForms/WPF, которые выполняются в среде Windows, в которой есть оконные сообщения, благодаря чему можно выполнить синхронный метод ShowDialog(). Реальность такова, что в Silverlight, в основном, используется асинхронная концепция, поэтому Вам придется использовать события, как в вышеприведенном примере.

    Можно, конечно, использовать функционал многопоточной блокировки — AutoResetEvent , но это не стоит того и не является общепринятой практикой.

    19 февраля 2011 г. 13:34
  • PashaPash, если я заменю дочернее окно на UserControl, я все же не знаю как решить мою задачу...

    19 февраля 2011 г. 13:47
  • Алексей напишу еще попроще, можут будут другие идеи:

    У меня есть форма регистрации пользователя на ней есть кнопка - "регистрация", я нажимаю на нее - сначала идет проверка на правильность заполнения даных, далее должно открытся окно согласия с лицензионным соглашением, типа такого, как на codeplexe, когда что-то скачиваеш, когда я соглашаюсь - все мои данные должни передаваться сервису, который взаемодействует с базой.

    19 февраля 2011 г. 13:53
  • Если заменить на UserControl – на нем будет вполне конкретная кнопка “I Agree”, OnClick можно вытянуть в главное окно:
    1. В UserControl объявляешь свое событие OnAgree.
    2. В главном окне подписываешься на него.
    3. После регистрации показываешь User Control.
    4. По клику на “I Agree” в контроле получаешь OnClick.
    5. В OnClick вызываешь this.Agree(...)
    6. В главном окне вызывается LicenseControl_OnAgree, в котором отправляешь данные сервису.
     
    Или можно взять готовый пример с codeplex, по ссылке из моего ответа выше...

    My blog
    19 февраля 2011 г. 14:22
  • Большое спасибо, все вышло)
    19 февраля 2011 г. 15:34
  • Ну так пример, который я привел выше, как раз такой функционал и реализует. Обработчик childWindow1_Button1Click в данном случае будет для обработки нажатия кнопки "Я согласен", а childWindow1_Button2Click — "Я не согласен".
    19 февраля 2011 г. 17:33