Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > WPF и Silverlight > Binding


Автор: Compositum 6.5.2009, 21:38
Создал класс:
Код

    class MyClass
    {
        public bool? IsChecked { 
            get; 
            set; }

Использую экземпляр этого класса в качестве поля класса, производного от Window:
Код

    class MyWindow : Window
    {
        MyClass myClass = new MyClass();
...

В окне размещаю CheckBox, который связываю с полем IsChecked. Хочу реализовать двустороннюю связь:
т.е. чтобы изменение значения CheckBox оказывало действие на поле IsChecked и наоборот: программное изменение поля IsChecked влияло и на значение CheckBox.
Код:
Код

using System;
using System.Collections.Generic;
//using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Controls.Primitives;
using System.Windows.Controls;
using System.Windows.Data;

namespace Petzold
{
    class MyWindow : Window
    {
        MyClass myClass = new MyClass();
        SolidColorBrush brush = new SolidColorBrush(Colors.Black);
        public MyWindow()
        {
           
            StackPanel stack = new StackPanel();
            Content = stack;
            stack.Margin = new Thickness(5);
            Button butTrue = new Button();
            butTrue.Content = "_True";
            butTrue.Click += new RoutedEventHandler(butTrue_Click);
            stack.Children.Add(butTrue);
            Button butFalse = new Button();
            stack.Children.Add(butFalse);
            butFalse.Content = "_False";
            butFalse.Click += new RoutedEventHandler(butFalse_Click);
            Button butNull = new Button();
            stack.Children.Add(butNull);
            butNull.Click += new RoutedEventHandler(butNull_Click);
            butNull.Content = "_Null";
            CheckBox box = new CheckBox();
            box.Content = "www";
            stack.Children.Add(box);
            Binding bind = new Binding("IsChecked");
            bind.Source = myClass;
            bind.Mode = BindingMode.TwoWay;//указываю, что связь должна быть двусторонней
            box.SetBinding(CheckBox.IsCheckedProperty, bind);
            box.Click += new RoutedEventHandler(box_Checked);
        }

        void butNull_Click(object sender, RoutedEventArgs e)
        {
            myClass.IsChecked = null;
            MessageBox.Show("Значение поля myClass: Null");
        }

        void butFalse_Click(object sender, RoutedEventArgs e)
        {
            myClass.IsChecked = false;
            MessageBox.Show(string.Format("Значение поля myClass: {0}", myClass.IsChecked));
        }

        void butTrue_Click(object sender, RoutedEventArgs e)
        {
            myClass.IsChecked = true;
            MessageBox.Show(string.Format("Значение поля myClass: {0}", myClass.IsChecked));
        }

        void box_Checked(object sender, RoutedEventArgs e)
        {
           MessageBox.Show(string.Format("Значение поля myClass: {0}", myClass.IsChecked));
        }
       
    }
    class MyClass
    {
        public bool? IsChecked { 
            get; 
            set; }
    }
}

Однако получаю лишь одностороннюю связь - при изменении значения объекта CheckBox значение поля IsChecked меняется. но ежели изменить значение IsChecked программно, то значение объекта CheckBox автоматом не изменится в соответствии с произведенным изменением.
Видать чего-то я недопонимаю...
Как реализовать двустороннюю связь?

Автор: -Mikle- 6.5.2009, 22:00
Ну а как по твоему Binding должен узнать об изменении поля myClass?
Ему нужно предоставить один из поддерживаемых им вариантов: INotifyPropertyChanged, либо (рекомендую) DependencyProperty.

Автор: Partizan 6.5.2009, 22:11
Цитата

namespace Petzold


Судя по всему изучаете по книжке Петцольда Applications = Markup + Code....


Имхо не очень удачная книжка... WPF Unleashed by Adam Nathan понравилась больше...

Автор: Compositum 6.5.2009, 22:15
Цитата(Partizan @ 6.5.2009,  22:11)
Цитата

namespace Petzold


Судя по всему изучаете по книжке Петцольда Applications = Markup + Code....


Имхо не очень удачная книжка... WPF Unleashed by Adam Nathan понравилась больше...

она самая. есть еще и Мак-Дональд, но Петцольд мне как-то более понятен зачастую. Хотя опечаток хватает и там и там...

Добавлено через 5 минут и 8 секунд
Цитата(-Mikle- @ 6.5.2009,  22:00)
Ну а как по твоему Binding должен узнать об изменении поля myClass?
Ему нужно предоставить один из поддерживаемых им вариантов: INotifyPropertyChanged, либо (рекомендую) DependencyProperty.

ДепенденсиПроперти, как я понял из прочтенного у Петцольда, удобно юзать в классах, посредством которых реализуется UI. 
А мне нужно сие выполнить применительно к классу, который является образом некой сущности (не визуальной). Посему, видимо, INotifyPropertyChanged - единственный вариант. Ранее я его не юзал, щас посмотрю инфу на эту тему. 
сиба.

Автор: -Mikle- 7.5.2009, 20:05
Ну не знаю, о чем там Петзольд писал... Считаю что если удобно, то юзай. 
DependencyObject не далеко от object стоит: DependencyObject : DispatcherObject : Object так что я не понимаю какая связь с UI у него.
Да и к тому же, ты ведь с CheckBox'ом работаешь, то есть свойство класса связано с UI.

Автор: WolfTheGrey 8.5.2009, 03:54
а еще можно при создании нового экземпляра класса ему в конструктор вкладывать такую строчку: Application.Current.MainWindow
тогда через экземпляр класса можно будет обратиться к классу родителю.
Код

public Slider sli;
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            Potomock win2 = new Potomock(Application.Current.MainWindow); win2.Show();
            Width = 150; Height = 150;
            sli = new Slider();
            sli.Width = 100; sli.Height = 10;
            sli.Minimum = 0; sli.Maximum = 100;
            sli.ValueChanged += delegate { win2.sli.Value = sli.Value; };
            Content = sli;
        }
        public class Potomock : Window
        {
            Window1 win; public Slider sli;
            public Potomock() { }
            public Potomock(Window wi)
            {
                win = (Window1)wi;
                Width = 150; Height = 150; Top = win.Top; Left = win.Left + 170;
                sli = new Slider();
                sli.Width = 100; sli.Height = 10;
                sli.Minimum = 0; sli.Maximum = 100;
                sli.ValueChanged += delegate { win.sli.Value = sli.Value; };
                Content = sli;
            }
        }

да и не трожте Петзольда.

Автор: -Mikle- 8.5.2009, 09:06
Цитата(WolfTheGrey @  8.5.2009,  06:54 Найти цитируемый пост)
а еще можно при создании нового экземпляра класса ему в конструктор вкладывать такую строчку: Application.Current.MainWindow

Нет, плохая это идея. Да и к теме топика не относится. Вопрос про связывание данных, а не про то как моно обращаться к форме и ее контролам.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)