Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / WPF, Silverlight Новый топик    Ответить
 WPF Binding: изменение объектов не обрабатывается байднигом  [new]
McCar
Member

Откуда: Саратов
Сообщений: 778
Джентельмены, я к WPF ной теме обращаюсь эпизодически, поэтому отнеситесь снисходительно если задаю глупый вопрос. Объясните плиз почему не срабатывает байндинг на примере следующего кода..
using System;
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using Xunit;
namespace Maria.Common.WPF.xUnit
{
public class UpdateDataTest
{
/// <summary>
/// Тест показывающий что изменение объектов не обрабатывается байднигом
/// </summary>
[Fact ]//(Skip = "Обламывается пока ")
public void UpdateData()
{
var tb = new TextBox();
var test2 = new Test2();
var b = new Binding
{
Mode = BindingMode.OneWay,
// , Path = new PropertyPath("Name")
Converter = new TestConverter()
};

tb.SetBinding(TextBox.TextProperty, b);
test2.Name = "Name";
Assert.True(tb.Text == test2.Name);
}
class Test2 : INotifyPropertyChanged
{
private string _Name;
public string Name
{
get { return _Name ;}
set
{
_Name = value;
OnPropertyChanged("Name"); } }

public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
class TestConverter : IValueConverter
{

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return ((Test2)value).Name;
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
}
}
}

---------
То есть свойство Name при изменении не отражается в забайнденном тексбоксе.
Я так понял что проблема в том что у события OnPropertyChanged нет обработчика.. В какой момент он должен назначаться? В общем в чем косяк?
17 июл 09, 13:35    [7428998]     Ответить | Цитировать Сообщить модератору
 Re: WPF Binding: изменение объектов не обрабатывается байднигом  [new]
SeVa
Member [заблокирован]

Откуда: Москва
Сообщений: 4324
Mode = BindingMode.TwoWay
17 июл 09, 14:24    [7429359]     Ответить | Цитировать Сообщить модератору
 Re: WPF Binding: изменение объектов не обрабатывается байднигом  [new]
McCar
Member

Откуда: Саратов
Сообщений: 778
SeVa
Mode = BindingMode.TwoWay

С конвертором ругается что " : Two-way binding requires Path or XPath." С Path просто как и раньше не срабатывает..
И.. при чем тут TwoWay. я так понимаю что OneWay это от объекта к текстбоксу поэтому вроде и так должно сработать.
17 июл 09, 15:06    [7429700]     Ответить | Цитировать Сообщить модератору
 Re: WPF Binding: изменение объектов не обрабатывается байднигом  [new]
McCar
Member

Откуда: Саратов
Сообщений: 778
Да, еще забыл
tb.DataContext = test2;
прописать.
Но, если его (DataContext) указать, то когда в для binding прописываеь Path - все отрабатывает нормально, у PropertyChanged есть обработчики. А если через IValueConverter -тогда по прежнему нет.
17 июл 09, 16:00    [7430066]     Ответить | Цитировать Сообщить модератору
 Re: WPF Binding: изменение объектов не обрабатывается байднигом  [new]
musson
Member

Откуда: SPb
Сообщений: 246
McCar


попробуй не кодом, а разметкой забиндить
17 июл 09, 16:36    [7430302]     Ответить | Цитировать Сообщить модератору
 Re: WPF Binding: изменение объектов не обрабатывается байднигом  [new]
McCar
Member

Откуда: Саратов
Сообщений: 778
musson
McCar


попробуй не кодом, а разметкой забиндить

да там на самом деле более сложный случай который я попытался свести к коротенькому тесту чтобы кто нибудь вразумил меня по поводу механизма байдинга через IValueConverter.
17 июл 09, 16:42    [7430340]     Ответить | Цитировать Сообщить модератору
 Re: WPF Binding: изменение объектов не обрабатывается байднигом  [new]
musson
Member

Откуда: SPb
Сообщений: 246
в студии в окне Output можно посмотреть ошибку, если она есть
17 июл 09, 16:43    [7430344]     Ответить | Цитировать Сообщить модератору
 Re: WPF Binding: изменение объектов не обрабатывается байднигом  [new]
Roman S. Golubin
Member

Откуда: 140002
Сообщений: 11541
McCar
Да, еще забыл
tb.DataContext = test2;
прописать.
Но, если его (DataContext) указать, то когда в для binding прописываеь Path - все отрабатывает нормально, у PropertyChanged есть обработчики. А если через IValueConverter -тогда по прежнему нет.


1. Без указания контекста свойство к чему привязываться будет? Контекст по любому надо указать.
2. Если указан Path="Name", то свойство TextProperty привязывается к интерфейсу INotifyPropertyChanged и ждет сообщений с e.propertyName == "Name".
3. Если Path не указывается, то свойство привязывается к объекту test2... Тяжелый случай То есть, отрабатывать привязка, теоретически, будет при отправке сообщения об изменении test2... А так как объект test2 у вас:
а) не меняется,
б) ни кто не отправляет сообщений об его изменении,
то, соответственно, обновления интерфейса и не происходит.

Надеюсь, понятно изложил :)
17 июл 09, 19:23    [7431342]     Ответить | Цитировать Сообщить модератору
 Re: WPF Binding: изменение объектов не обрабатывается байднигом  [new]
McCar
Member

Откуда: Саратов
Сообщений: 778
Roman S. Golubin
McCar
Да, еще забыл
tb.DataContext = test2;
прописать.
Но, если его (DataContext) указать, то когда в для binding прописываеь Path - все отрабатывает нормально, у PropertyChanged есть обработчики. А если через IValueConverter -тогда по прежнему нет.


1. Без указания контекста свойство к чему привязываться будет? Контекст по любому надо указать.
2. Если указан Path="Name", то свойство TextProperty привязывается к интерфейсу INotifyPropertyChanged и ждет сообщений с e.propertyName == "Name".
3. Если Path не указывается, то свойство привязывается к объекту test2... Тяжелый случай То есть, отрабатывать привязка, теоретически, будет при отправке сообщения об изменении test2... А так как объект test2 у вас:
а) не меняется,
б) ни кто не отправляет сообщений об его изменении,
то, соответственно, обновления интерфейса и не происходит.

Надеюсь, понятно изложил :)

Ну с датаконтекстом это я просто недокопипастил.
А насчет остального.. Кажется начинает доходить. Я видимо выдавал желаемое за действительное когда считал что задать Converter это тоже самое что задать Path - но в другой форме. Похоже на то что байдинг не отслеживает никакие изменения объекта до тех пор пока не задашь в явном виде Path. Причем если задать одновременно и то и то
(
var b = new Binding
{
Mode = BindingMode.OneWay,
Converter = new TestConverter(),
Path = new PropertyPath("Name")
};
)
-обработчики события PropertyChanged подключаются, но уже в этих обработичках на изменненное свойство Name накладывается конвертор, которое естесвенно не может скастить string в тестовый класс.
Если задать пустой PropertyPath("") - обработчики молча не подключаются,
если несущесвующий PropertyPath("aaaa") - тогда в Output окно выводится ошибка байдинга и обработчики не подключаются..
То есть - я так понял, если мы задаем конвертор и не задаем Path, - мы не можем воспользоватсья OneWay или TwoWay байдингом? то есть нет никакого способа заставить байдинг подключать обработчики для PropertyChanged кроме как указав Path?
У меня не просто теоретический вопрос, дело в том что в существующем проекте байдинг сделан через IConvertor ы, и сейчас встала задача обновления интерефейса одновременно с изменениями объектов к этому интерфейсу привязанных.
18 июл 09, 15:31    [7432268]     Ответить | Цитировать Сообщить модератору
 Re: WPF Binding: изменение объектов не обрабатывается байднигом  [new]
eLVik
Member

Откуда: г. Сыктывкар
Сообщений: 108
Здравствуйте.
Столкнулся с аналогичной проблемой. Поиск решения привел в эту ветку.

Roman S. Golubin

1. Без указания контекста свойство к чему привязываться будет? Контекст по любому надо указать.
2. Если указан Path="Name", то свойство TextProperty привязывается к интерфейсу INotifyPropertyChanged и ждет сообщений с e.propertyName == "Name".
3. Если Path не указывается, то свойство привязывается к объекту test2... Тяжелый случай То есть, отрабатывать привязка, теоретически, будет при отправке сообщения об изменении test2... А так как объект test2 у вас:
а) не меняется,
б) ни кто не отправляет сообщений об его изменении,
то, соответственно, обновления интерфейса и не происходит.

Надеюсь, понятно изложил :)


Да, видимо у нас с автором топика тяжелый случай №3.
Данный пост навел на следующую мысль - нужно создать класс-обертку и использовать его экземпляр в качестве DataContext.

    // Исходный класс.
    public class FlyProject: INotifyPropertyChanged
    {

        bool _isPolygonMode = false;

        public bool IsPolygonMode
        {
            get { return _isPolygonMode; }
            set 
            {
                if (value != _isPolygonMode)
                {
                    _isPolygonMode = value;
                    NotifyPropertyChanged("IsPolygonMode");
                }
            }
        }

        int _bp = 0;

        public int Bp
        {
            get { return _bp; }
            set
            {
                _bp = value;
                this.NotifyPropertyChanged("Bp");
            }
        }

        List<Point> _pathPoints = new List<Point>();

        public List<Point> PathPoints
        {
            get { return _pathPoints; }
        }

        public FlyProject()
        {
            // набор точек для примера.
            _pathPoints.Add(new Point(50, 75));
            _pathPoints.Add(new Point(100, 30));
            _pathPoints.Add(new Point(70, 15));
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    
    // Класс-обертка
    public class FlyProjectContext: INotifyPropertyChanged
    {

        FlyProject _project = null;
        public FlyProject Project 
        {
            get
            {
                return _project;
            }
            set
            {
                if (_project != null)
                    _project.PropertyChanged -= _project_PropertyChanged;

                _project = value;
                _project.PropertyChanged += new PropertyChangedEventHandler(_project_PropertyChanged);
                
            }
        }        

        public FlyProjectContext()
        {
            Project = new FlyProject();
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        private void _project_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            this.NotifyPropertyChanged("Project");
        }
    }

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        FlyProjectContext _projectContext = new FlyProjectContext();

        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = _projectContext;
        }
    }

Теперь в биндинге можно указать Path

<Window.Resources>
<c:PathPointsConverter x:Key="conv1" />
</Window.Resources>
<!-- ... -->
<Canvas Width="350" Height="200">
<Path Stroke="Black" Data="{Binding Path='Project', Converter={StaticResource conv1}, Mode=OneWay}" />
</Canvas>
<!-- ... -->
<TextBox Text="{Binding Path='Project.Bp', Mode=OneWay}" />
10 янв 10, 23:46    [8163033]     Ответить | Цитировать Сообщить модератору
Все форумы / WPF, Silverlight Ответить