none
WPF TextBox Binding RRS feed

  • Вопрос

  • Добрый день!

    Прошу помощи в следующей проблеме:

    TextBox обновляется только в самом конце выполнения функции CESolveAutoS, а нужно, чтобы он отображал все в реальном времени по мере изменения свойства TextBox.Text.

    XAML:

    <Grid> <TextBox Name="info"

    Margin="2"

    IsReadOnly="True"

    Text="{Binding Source=en, Path=ModelNumber, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/> </Grid>

    Главное окно:

    public partial class MainWindow : Window
    {
            public MainWindow()
            {
                InitializeComponent();
    
                Binding binding = new Binding();
                binding.Source = en;
                binding.Path = new PropertyPath("type");
                binding.Mode = BindingMode.TwoWay;
                info.SetBinding(TextBox.TextProperty, binding);
            }
    
            private void MenuItem_Click_6(object sender,         RoutedEventArgs e)
            {
                try
                {
                    CEAutoReport car = new CEAutoReport();
                    CESolver.CESolveAutoS(this.info, ReadClass.listOfOpenFiles[listBoxChangeFile.SelectedIndex], 
                        (decimal)(Variables.SETTING_DIAM_M * Variables.SETTING_SCALE_M), ReadClass.listOfOpenFiles[listBoxChangeFile.SelectedIndex].сenter);
                    MessageBox.Show(car.ce + "\n" + car.delta + "\n" + car.sumBrWON + "\n" + car.temp2 + "\n" + car.time);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }
    }
    
    class Type : INotifyPropertyChanged
        {
    
            private string str;
            public string type
            {
                get { return str; }
                set
                {
                    str = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("type"));
                }
            }
            public event PropertyChangedEventHandler PropertyChanged;
            public void OnPropertyChanged(PropertyChangedEventArgs e)
            {
                if (PropertyChanged != null)
                    PropertyChanged(this, e);
            }
    
            public Type()
            {
                type = "";
            }
        }

    и отдельный класс где я меняю TextBox.Text:

    public class CESolver { public static CEAutoReport CESolveAutoS(System.Windows.Controls.TextBox tb,

    FileData fileData, decimal DiamInPix, Point center) { string str = string.Format("{0} \t Начало автоматической обработки одного кадра...", DateTime.Now); tb.Text += str; tb.UpdateLayout(); } }


    17 октября 2015 г. 9:41

Ответы

Все ответы

  • Я пытался понять ваш код, но с C# у меня сложности, поэтому понял не все.

    Понял что у вас за каким то боком привязка и в XAML и в коде. Еще понял, что все должно работать нормально, а раз не работает, то на время выполнения функции зависает основной поток.

    Пусть сишники меня поправят, если что


    VB.Net - WPF, UWP

    17 октября 2015 г. 10:06
  • Согласен насчет двойной привязки.

    Эти строки вообще убрал:

    Binding binding = new Binding();
    binding.Source = en;
    binding.Path = new PropertyPath("type");
    binding.Mode = BindingMode.TwoWay;
    info.SetBinding(TextBox.TextProperty, binding)

    А xaml Отредактировал следующим образом:

    <TextBox Name="info" Margin="2" IsReadOnly="True" Text="{Binding Source=en, Path=type, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/> 

    Но проблема осталась.

    17 октября 2015 г. 10:15
  • У меня с Binding общение на Вы и шепотом, но попробую вставит свои пять копеек...

    Вы пишете:

    public string type
            {
                get { return str; }
                set
                {
                    str = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("type"));
                }
            }
    Вы описываете строку в классе с именем type, в обработке строки type изменяете строку str, а пишете, что обновили строку type, где-то тут собака порылась... Программа перерисовывает строку type, а в ней изменений то и не было...

    17 октября 2015 г. 13:46
  • Проблема решена использованием async delegate.

    Всем спасибо!

    17 октября 2015 г. 13:48
  • У меня с Binding общение на Вы и шепотом, но попробую вставит свои пять копеек...

    str это внутренняя переменная которая хранит значение свойства. Ту все ОК.

    А вот проблема как я и говорил была в блокировке потока.


    VB.Net - WPF, UWP

    17 октября 2015 г. 14:29
  • Вы были правы, но реализовывать мне все равно придется по другому и пока не знаю как...

    Возможно существуют уже готовые решения?

    Смысл в том, что нужно из другого класса передавать данные о результатах выполнения функции на главную форму в реально времени.

    17 октября 2015 г. 15:59
  • Вы с многопоточностью знакомы?

    VB.Net - WPF, UWP

    17 октября 2015 г. 16:49
  • Как описывал выше - да. Проблему решил, но получилось не очень элегантно
    17 октября 2015 г. 18:18
  • str это внутренняя переменная которая хранит значение свойства. Ту все ОК.
    Просто я Binding использую для отображения списка пользователей в чате. Пока не знаю как, но работало... И у меня сложилось впечатление, что для обновления отображаемого поля, после присвоения, необходимо указывать именно его в событии.

    str = value;

    OnPropertyChanged(new PropertyChangedEventArgs("type"));

    if (PropertyChanged != null)PropertyChanged(this, e);

    А тут в коде событие обновления запускается для названия "type", а я пишу у себя обычно "str" ведь только оно поменялось, значит его и нужно обновлять.
    18 октября 2015 г. 5:48
  • Вы с многопоточностью знакомы?

    VB.Net - WPF, UWP

    Нет не знакома. Я такую же проблему решала через статический класс. В статическом классе описываю все "глобальные переменные", а потом использую их в проекте, в том числе и список на основе класса.
    class XXX : INotifyPropertyChanged
    Делаю Binding на главной форме этого класса, а изменение списка ведется на всех формах проекта. Это не правильно? Есть способы лучше?
    18 октября 2015 г. 5:54
  • Делаю Binding на главной форме этого класса, а изменение списка ведется на всех формах проекта. Это не правильно? Есть способы лучше?
    Лилиия давайте не будем этот топик засорять. Может создадите новое обсуждение и там поболтаем. Есть подозрения, что вам можно подкинуть пару новых знаний, которые упростят жизнь )))

    VB.Net - WPF, UWP

    • Изменено LXGDARK 18 октября 2015 г. 6:54
    18 октября 2015 г. 6:54
  • Лилиия давайте не будем этот топик засорять. Может создадите новое обсуждение и там поболтаем. Есть подозрения, что вам можно подкинуть пару новых знаний, которые упростят жизнь )))

    Автор топика: Смысл в том, что нужно из другого класса передавать данные о результатах выполнения функции на главную форму в реально времени.

    Я и автор этого топика решаем одинаковую задачу. Отображать данные класса на главной форме в реальном времени, а доступ к классу необходимо обеспечить со всех форм проекта. Изменения могут возникать асинхронно и еще какие-то умные слова, говорящие о том, что данные класс подвергается различным изменениям, которые главная форма не в силах проконтролировать.
    18 октября 2015 г. 9:18
  • То о чем вы говорите называется MVVM, но я не поэтому предложил отдельный топик. Меня смутило рассуждение про str и Type. Это уже к данному топику отношения не имеет. Это скорее тема построения классов в принципе, а не только для привязки.

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


    VB.Net - WPF, UWP

    18 октября 2015 г. 10:01
  • То о чем вы говорите называется MVVM, но я не поэтому предложил отдельный топик. Меня смутило рассуждение про str и Type. Это уже к данному топику отношения не имеет. Это скорее тема построения классов в принципе, а не только для привязки.

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


    VB.Net - WPF, UWP

    Ага точно MVVM прикольное сочетание букв. Я не готова пока обсуждать классы, так как ни как не могу их понять. Создать класс привязать его к элементам формы по MVVM тыча в книжку пальчиком могу, но как только заходит разговоры о наследовании и прочем, лучше застрелите...

    Но за предложение спасибо!

    18 октября 2015 г. 10:43
  • Если еще актуально, вот как эту задачу решил я:

    В xaml ничего особого:

    <Grid>
    	<TextBox Name="info" Margin="2" VerticalScrollBarVisibility="Auto" ScrollViewer.CanContentScroll="True" IsUndoEnabled="False" TextWrapping="Wrap"/>
    </Grid>


    Запуск функции из другого класса выглядит так:

    	public delegate CEAutoReport CESolveAutoSdel(Type en, FileData fileData, decimal DiamInPix, Point center);
            private void MenuItem_Click_6(object sender, RoutedEventArgs e)
            {
                try
                {
                    CESolveAutoSdel del = CESolver.CESolveAutoS;
                    IAsyncResult ar = del.BeginInvoke(en, ReadClass.listOfOpenFiles[listBoxChangeFile.SelectedIndex],
                        (decimal)(Variables.SETTING_DIAM_M * Variables.SETTING_SCALE_M), ReadClass.listOfOpenFiles[listBoxChangeFile.SelectedIndex].сenter, null, null);            
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }

    Класс Type для вывода инфы в TextBox:

    public class Type : INotifyPropertyChanged
        {
    
            private string str;
            public string type
            {
                get { return str; }
                set
                {
                    str = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("type"));
                }
            }
            public event PropertyChangedEventHandler PropertyChanged;
            public void OnPropertyChanged(PropertyChangedEventArgs e)
            {
                if (PropertyChanged != null)
                    PropertyChanged(this, e);
            }
    
            public Type()
            {
                type = "";
            }
        }

    ну и собственно сама функция в которой мы можем обращаться к объекту класса Type для вывода хода выполнения этой функции в TextBox (жирным выделено то, что нужно):

    public static CEAutoReport CESolveAutoS(Type en, FileData fileData, decimal DiamInPix, Point center)
            {
                try
                {
                    int nWorkerThreads;
                    int nCompletionThreads;
                    ThreadPool.GetMaxThreads(out nWorkerThreads, out nCompletionThreads);
                    en.type += string.Format("Максимальное количество потоков: {0} \nПотоков ввода-вывода доступно: {1}\n", nWorkerThreads, nCompletionThreads);
                    en.type += string.Format("Начало обработки кадра {0}... \n", fileData.name);
    		}
    	}

    Схема такая, что мы просто запускаем выполнение функции в новом асинхронном потоке.

    1 ноября 2015 г. 16:48