Привязать контроль к собственности не работает - PullRequest
0 голосов
/ 18 марта 2012

Я создаю приложение, которое использует несколько потоков, в результате я хочу попытаться использовать UIControls в своем коде как можно меньше. Я делаю это, привязывая элементы управления к свойству в моем коде, и таким образом я могу обновлять элемент управления, изменяя это свойство, не имеет значения, обновляется ли это свойство в другом потоке. В любом случае я создаю следующий код, чтобы класс создавал привязки из меня.

public static class MyExtensionMethods 
{

    public static TextBoxBind<T> BindTextBox<T>(this TextBox textbox, string property=null)
    {
        return new TextBoxBind<T>(textbox,property);
    }
}



public class TextBoxBind<T> : INotifyPropertyChanged
{
    string property;

    protected T _Value;
    public T Value
    {
        get { return _Value; }
        set { _Value = value; OnPropertyChanged(property); }
    }

    public event PropertyChangedEventHandler PropertyChanged = delegate { };
    protected void OnPropertyChanged(string propertyName){
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    public TextBoxBind(TextBox textbox, string property)
    {
        if (property == null)
        {
            property = "Value";
        }
        this.property = property;

        Binding b = new Binding(property)
       {
            Source = this
       };

        b.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
        textbox.SetBinding(TextBox.TextProperty, b);
    }
}

И на моем XAML у меня есть:

 <TextBox  Name="textBox2"  />

Поэтому я смогу использовать первый код, который я разместил как:

        var newTextBox2 = textBox2.BindTextBox<int>();
        newTextBox2.Value = 50; // this will update the textBox2.Text = "2"
        // also every time I update the value of textBox2  newTextBox2.Value will update as well

Проблема в том, что я пытаюсь привязать его к пользовательскому объекту. Возьмите этот код, например:

    public class Person 
    {
        public string Name { get; set; }
        public string Age { get; set; }

        public override string ToString()
        {
            return Age.ToString();
        }            

    }

    void LogIn_Loaded(object sender, RoutedEventArgs e)
    {
        txtUsuario.Focus();

        var newTextBox2 = textBox2.BindTextBox<Person>("Age");

        // here newTextBox2 never updates....


    }

Ответы [ 2 ]

1 голос
/ 18 марта 2012

Когда дело доходит до привязки данных, нужно обновить объект (не имеет значения свойство CLR или DependencyObject) из того же потока, в котором работает пользовательский интерфейс. Если у вас есть элемент пользовательского интерфейса, связанный с чем-то в коде, обновление этого из отдельного потока приведет к исключению. Однако вы всегда можете получить свой поток пользовательского интерфейса и выполнить обновление свойства там. Вот фрагмент кода, который я использую в аналогичной ситуации:

ThreadStart updateLogs = delegate()
{
    ObservableCollection<LogMessage> newLogs = this._parcer.Parce();
    foreach (LogMessage log in newLogs)
        LogMessages.Add(log);
};
App.Current.Dispatcher.BeginInvoke(updateLogs, null);

Этот блок кода выполняется в потоке, отличном от одного пользовательского интерфейса. Поэтому я извлекаю код, который фактически обновляет источник привязки (то есть LogMessages) в делегат updateLogs, а затем запускаю этот делегат в потоке пользовательского интерфейса, передавая его диспетчеру приложения.

Тем не менее, приложение WPF может иметь более одного диспетчера, если, например, вы создаете отдельные окна в отдельных потоках, хотя такой подход встречается редко. Но на всякий случай класс DependencyObject имеет свойство Dispatcher, которое ссылается на Диспетер, которому принадлежит этот объект.

0 голосов
/ 18 марта 2012

OnPropertyChanged(property); должно указывать на Значение, так как это название вашей собственности.Это не должно указывать на тип T.Поэтому этот код неверен:

if (property == null) 
{ 
  property = "Value"; 
}

, поскольку свойство всегда должно быть "Value"

public T Value     
{     
    get { return _Value; }     
    set { _Value = value; OnPropertyChanged("Value"); }     
}  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...