Вопрос по привязке данных WPF - PullRequest
1 голос
/ 15 января 2010

Я написал очень короткое приложение, в котором я пытаюсь достичь следующего: CheckBox меняет свое состояние с кода. Я подключил интерфейс INotifyPropertyChanged и ожидал увидеть некоторые результаты, но, очевидно, приложение ничего не делает. Что-то не так с привязкой данных?

Window1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;

namespace WpfTEST
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window, INotifyPropertyChanged
    {
        public Window1()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(Window1_Loaded);
            this.PropertyChanged += new PropertyChangedEventHandler(Window1_PropertyChanged);
        }

        public bool Flag
        {
            get { return m_flag; }
            set
            {
                m_flag = value; 
                OnPropertyChanged("Flag");
            }
        }

        private bool m_flag = false;

        void Window1_Loaded(object sender, RoutedEventArgs e)
        {
            this.m_cbox.DataContext = this;

            for (int i = 0; i < 1000; i++)
            {
                Flag = (i % 2 == 0);
                Thread.Sleep(200);
            }


        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(string name)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
        void Window1_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {

        }

        #endregion
    }
}

Window1.xaml

<Window x:Class="WpfTEST.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300" x:Name="window">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="0.5*" />
            <ColumnDefinition Width="0.5*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="0.5*" />
            <RowDefinition Height="0.5*" />
        </Grid.RowDefinitions>
        <CheckBox x:Name="m_cbox" Content="Let's see what happens" Grid.Row="2" Grid.Column="2" Grid.RowSpan="1" Grid.ColumnSpan="1" IsChecked="{Binding Path=Flag, ElementName=window, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
    </Grid>
</Window>

Ответы [ 2 ]

2 голосов
/ 15 января 2010

Единственная реальная проблема, которую я вижу с вашим кодом - это цикл сна в Loaded. Это приводит к тому, что поток пользовательского интерфейса перестает отвечать на запросы в течение всего цикла, поскольку вы переводите поток пользовательского интерфейса в заблокированное состояние.

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

<Window x:Class="WpfTEST.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300" x:Name="window">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="0.5*" />
            <ColumnDefinition Width="0.5*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="0.5*" />
            <RowDefinition Height="0.5*" />
        </Grid.RowDefinitions>
        <!-- I added this button: -->
        <Button Click="Button_Click" Grid.Row="0" Grid.Column="0"/>
        <CheckBox x:Name="m_cbox" Content="Let's see what happens" Grid.Row="2" Grid.Column="2" Grid.RowSpan="1" Grid.ColumnSpan="1" IsChecked="{Binding Path=Flag, ElementName=window, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
    </Grid>
</Window>

и в коде позади:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;

namespace WpfTEST {
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window, INotifyPropertyChanged {
        public Window1() {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(Window1_Loaded);
            this.PropertyChanged += new PropertyChangedEventHandler(Window1_PropertyChanged);
        }

        public bool Flag {
            get { return m_flag; }
            set {
                m_flag = value;
                OnPropertyChanged("Flag");
            }
        }

        private bool m_flag = false;

        void Window1_Loaded( object sender, RoutedEventArgs e ) {
            this.m_cbox.DataContext = this;
            Flag = false;
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged( string name ) {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
        void Window1_PropertyChanged( object sender, PropertyChangedEventArgs e ) {

        }

        #endregion

        private void Button_Click( object sender, RoutedEventArgs e ) {
            Flag = !Flag;
        }
    }
}

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

1 голос
/ 15 января 2010

Это будет работать, только если ваше свойство Flag является свойством зависимости. Чтобы заставить это работать самым простым способом, я могу думать, что я сделал бы следующее: измените свою привязку на:

IsChecked = "{Binding Path = Flag, Mode = TwoWay}"

и в вашем конструкторе в вашем коде сделайте это:

DataContext = this;

или в XAML

DataContext = "{Binding RelativeSource = {RelativeSource self}}" "1011 *

Примечание. Флаг не обязательно должен быть свойством зависимости, если вы устанавливаете текстовый текст данных в качестве окна.

...