Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / WPF, Silverlight Новый топик    Ответить
Топик располагается на нескольких страницах: 1 2      [все]
 DataContext биндинг.  [new]
Eld Hasp
Member

Откуда:
Сообщений: 178
В VM есть следующие свойства
        private List<Client> clients;
        public List<Client> Clients { get => clients; set { clients = value; OnPropertyChanged(); } }


        private Client _selectedClient;
        public Client SelectedClient
        {
            get => _selectedClient;
            set
            {
                _selectedClient = value;
                if (!IsEdit) CurrentClient = SelectedClient;
                OnPropertyChanged();
            }
        }

        private Client _currentClient;
        public Client CurrentClient { get => _currentClient; set { _currentClient = value; OnPropertyChanged(); } }

        private bool _isEdit;
        public bool IsEdit { get => _isEdit; set { if (_isEdit && !value) CurrentClient = SelectedClient; _isEdit = value; OnPropertyChanged(); } }
В обычном режиме (IsEdit=false) в CurrentClient копируется значение SelectedClient.
В окне к свойству Name свойства CurrentClient привязан TextBox следующим образом
        <StackPanel Margin="10" Grid.Column="1" DataContext="{Binding CurrentClient}">
            <TextBlock Text="ФИО Клиента"/>
            <TextBox Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
        </StackPanel>
Если в режиме редактирования (IsEdit=true) CurrentClient в методе присваиваю другое значение и потом вносятся какие-либо изменения в TextBox'е, то все привязки в окне рушатся.
Если привязать так
        <StackPanel Margin="10" Grid.Column="1">
            <TextBlock Text="ФИО Клиента"/>
            <TextBox Text="{Binding CurrentClient.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
        </StackPanel>
То работает нормально, но так привязывать неудобно. У CurrentClient свойств и привязанных к ним элементов много. Удобнее установить общий DataContext в StackPanel.
Чего я не догоняю? Если CurrentClient сделать свойством зависимостей это решит проблему? Или в в чём-то другом проблема?
30 ноя 18, 14:56    [21750087]     Ответить | Цитировать Сообщить модератору
 Re: DataContext биндинг.  [new]
Shocker.Pro
Member

Откуда: ->|<- :адуктО
Сообщений: 19959
Eld Hasp
то все привязки в окне рушатся.
не смог разгадать смысл фразы
30 ноя 18, 15:04    [21750107]     Ответить | Цитировать Сообщить модератору
 Re: DataContext биндинг.  [new]
Eld Hasp
Member

Откуда:
Сообщений: 178
Shocker.Pro
Eld Hasp
то все привязки в окне рушатся.
не смог разгадать смысл фразы
В буквальном смысле. Даже привязки не связанные с CurrentClient перестают почему-то работать.
30 ноя 18, 15:17    [21750131]     Ответить | Цитировать Сообщить модератору
 Re: DataContext биндинг.  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 37082
Eld Hasp
потом вносятся какие-либо изменения в TextBox'е,
встречные? От кого?
Я так понял, что поле чисто справочное и биндинг в одну сторону.
30 ноя 18, 15:18    [21750133]     Ответить | Цитировать Сообщить модератору
 Re: DataContext биндинг.  [new]
Eld Hasp
Member

Откуда:
Сообщений: 178
Окно
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <DataGrid ItemsSource="{Binding Clients}" AutoGenerateColumns="False" IsReadOnly="True" SelectedItem="{Binding SelectedClient}">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding ID}" ClipboardContentBinding="{x:Null}" Header="ID" Width="*"/>
                <DataGridTextColumn Binding="{Binding Name}" ClipboardContentBinding="{x:Null}" Header="Фамилия, имя, отчество" Width="6*"/>
            </DataGrid.Columns>
        </DataGrid>
        <StackPanel Margin="10" Grid.Column="1" DataContext="{Binding CurrentClient}">
            <TextBlock Text="ФИО Клиента"/>
            <TextBox Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsEnabled="{Binding DataContext.IsEdit, ElementName=window}"/>
        </StackPanel>
        <Grid Grid.Row="1" Grid.ColumnSpan="2">
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Button  Margin="10" Content="Редактировать" Command="{Binding EditCommand}" />
            <Button Grid.Column="1" Margin="10" Content="Сохранить изменения" Command="{Binding SaveChangeCommand}" CommandParameter="{Binding CurrentClient}"   IsEnabled="{Binding DataContext.IsEdit, ElementName=window}"/>
            <Button Grid.Column="2" Margin="10" Content="Выйти" Command="{Binding ExitCommand}"   IsEnabled="{Binding DataContext.IsEdit, ElementName=window}"/>
        </Grid>
    </Grid>
ViewModel
    public class ViewModelDSC : OnPropertyChangedClass
    {
        private List<Client> clients;
        public List<Client> Clients { get => clients; set { clients = value; OnPropertyChanged(); } }


        private Client _selectedClient;
        public Client SelectedClient
        {
            get => _selectedClient;
            set
            {
                _selectedClient = value;
                if (!IsEdit) CurrentClient = SelectedClient;
                OnPropertyChanged();
            }
        }

        private Client _currentClient;
        public Client CurrentClient { get => _currentClient; set { _currentClient = value; OnPropertyChanged(); } }

        private bool _isEdit;
        public bool IsEdit { get => _isEdit; set { if (_isEdit && !value) CurrentClient = SelectedClient; _isEdit = value; OnPropertyChanged(); } }


        /// <summary>Поле для хранения значения свойства EditCommand</summary>
        private ICommand _editCommand { get; set; }
        /// <summary>Свойство для привязки команды Редактировать</summary>
        public ICommand EditCommand => _editCommand ?? (_editCommand = new RelayCommand(OnEdit));
        /// <summary>Метод для команды EditCommand</summary>
        protected virtual void OnEdit(object value) { IsEdit = true; CurrentClient = SelectedClient.Copy(); }

        /// <summary>Поле для хранения значения свойства RemoveCommand</summary>
        private ICommand _saveChangeCommand { get; set; }
        /// <summary>Свойство для привязки команды Удалить</summary>
        public ICommand SaveChangeCommand => _saveChangeCommand ?? (_saveChangeCommand = new RelayCommand(OnSaveChange));
        /// <summary>Метод для команды RemoveCommand</summary>
        protected virtual void OnSaveChange(object value)
        {
            MessageBox.Show(value.ToString());
            if (IsEdit && value is Client client)
            {
                if (Model.ChangeID(client))
                {
                    IsEdit = false;
                }
                else
                    System.Windows.MessageBox.Show("Ошибка внесения изменений!");
            }
        }
        /// <summary>Поле для хранения значения свойства EditCommand</summary>
        private ICommand _exitCommand { get; set; }
        /// <summary>Свойство для привязки команды Редактировать</summary>
        public ICommand ExitCommand => _exitCommand ?? (_exitCommand = new RelayCommand(OnExit));
        /// <summary>Метод для команды EditCommand</summary>
        protected virtual void OnExit(object value)
        {
            // Проверка были изменения или нет
            if (IsEdit && !CurrentClient.Equals(SelectedClient))
                // Если были изменения, то вывод предупреждения
                if (MessageBox.Show("Данные не были сохранены!\nПри выходе изменения будут утеряны\nВсё равно выйти?", "Предупреждение!", MessageBoxButton.YesNo)
                     == MessageBoxResult.No)
                    return;
            IsEdit = false;
           
        }


        private ModelDSC _model;

        public ModelDSC Model
        {
            get { return _model; }
            set { _model = value; Clients = Model.GetClients(); }
        }


        public ViewModelDSC() { }
        public ViewModelDSC(string FileName)
        {
            Model = ModelDSC.Load(FileName);
        }
    }
Если войти в режим редактирования, и изменить поле в TextBox, то ни одна привязка после это не работает.
Проект приложил целиком - на всякий случай.

К сообщению приложен файл (SQL_ru_Wpf.7z - 30Kb) cкачать
30 ноя 18, 15:23    [21750142]     Ответить | Цитировать Сообщить модератору
 Re: DataContext биндинг.  [new]
Eld Hasp
Member

Откуда:
Сообщений: 178
Petro123
Eld Hasp
потом вносятся какие-либо изменения в TextBox'е,
встречные? От кого?
Я так понял, что поле чисто справочное и биндинг в одну сторону.
Реально несколько полей. В режиме редактирования связь от поля к VM тоже есть.
30 ноя 18, 15:25    [21750148]     Ответить | Цитировать Сообщить модератору
 Re: DataContext биндинг.  [new]
Shocker.Pro
Member

Откуда: ->|<- :адуктО
Сообщений: 19959
Eld Hasp
Даже привязки не связанные с CurrentClient перестают почему-то работать.
Пока я увидел, что перестает работать привязка к SelectedClient, остальные-то работают, какие привязки перестали еще работать?
30 ноя 18, 15:40    [21750193]     Ответить | Цитировать Сообщить модератору
 Re: DataContext биндинг.  [new]
Eld Hasp
Member

Откуда:
Сообщений: 178
Shocker.Pro
Eld Hasp
Даже привязки не связанные с CurrentClient перестают почему-то работать.
Пока я увидел, что перестает работать привязка к SelectedClient, остальные-то работают, какие привязки перестали еще работать?
там сейчас три привязки. TextBox к CurrentClient.Name, DataGdrid к SelectedClient, параметры в кнопке к CurrentClient.
Остальные, извиняюсь, забыл убрать. Их хотел убрать из примера - забыл. Скинул с ними.
30 ноя 18, 15:49    [21750216]     Ответить | Цитировать Сообщить модератору
 Re: DataContext биндинг.  [new]
Shocker.Pro
Member

Откуда: ->|<- :адуктО
Сообщений: 19959
90% виновата перегрузка эквивалентности для Client, в результате которой не порождаются изменения при операциях типа CurrentClient = SelectedClient - объекты по сути разные, но они эквивалентны.
30 ноя 18, 15:51    [21750225]     Ответить | Цитировать Сообщить модератору
 Re: DataContext биндинг.  [new]
Eld Hasp
Member

Откуда:
Сообщений: 178
MessageBox в к команде кнопки сохранить должен выводить изменяемый экземпляр Client, а Выводит то с которого делалась копия.
30 ноя 18, 15:52    [21750227]     Ответить | Цитировать Сообщить модератору
 Re: DataContext биндинг.  [new]
Eld Hasp
Member

Откуда:
Сообщений: 178
Shocker.Pro
90% виновата перегрузка эквивалентности для Client, в результате которой не порождаются изменения при операциях типа CurrentClient = SelectedClient - объекты по сути разные, но они эквивалентны.
ОК! Попробую сейчас это исправить. Результат отпишу.
30 ноя 18, 15:53    [21750232]     Ответить | Цитировать Сообщить модератору
 Re: DataContext биндинг.  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 37082
Eld Hasp
там сейчас три привязки.
если не заработает, то скрин и use case.
30 ноя 18, 16:19    [21750307]     Ответить | Цитировать Сообщить модератору
 Re: DataContext биндинг.  [new]
Eld Hasp
Member

Откуда:
Сообщений: 178
Shocker.Pro
90% виновата перегрузка эквивалентности для Client, в результате которой не порождаются изменения при операциях типа CurrentClient = SelectedClient - объекты по сути разные, но они эквивалентны.
Действительно, для примера это решило все проблемы. Исправлю основной проект - тоже отпишу.
Что-то я упустил такую особенность Equals. В XAML объекты на по адресу, а через этот метод идентифицируются?
Надо перечитать...
30 ноя 18, 19:13    [21750682]     Ответить | Цитировать Сообщить модератору
 Re: DataContext биндинг.  [new]
Shocker.Pro
Member

Откуда: ->|<- :адуктО
Сообщений: 19959
Eld Hasp
В XAML объекты на по адресу, а через этот метод идентифицируются?
Возможно, это особенность работы SelectedItem, ибо там коллекция, а какой-нибудь FirstOrDefault будет искать через Equals, я в общем, глубоко не стал копать.
Так или иначе, с целью проверки измененных полей переопределять Equals я бы не стал, потому что это много на что влияет, в частности, как раз на Linq-операции.
30 ноя 18, 19:18    [21750685]     Ответить | Цитировать Сообщить модератору
 Re: DataContext биндинг.  [new]
Shocker.Pro
Member

Откуда: ->|<- :адуктО
Сообщений: 19959
С другой стороны...
Eld Hasp
В XAML объекты на по адресу, а через этот метод идентифицируются?
Надо перечитать...
В учебниках я этого не встречал. Но для того, чтобы сгененировать событие изменения свойства зависимости, проверка, возможно, осуществляется через Equals, можно тупо глянуть в исходники.

Отпишись по результатам )
30 ноя 18, 19:21    [21750689]     Ответить | Цитировать Сообщить модератору
 Re: DataContext биндинг.  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 37082
Eld Hasp,
Почему выделенный объект не сделать свойство через номер, индекс, айдишник?
30 ноя 18, 19:23    [21750693]     Ответить | Цитировать Сообщить модератору
 Re: DataContext биндинг.  [new]
Shocker.Pro
Member

Откуда: ->|<- :адуктО
Сообщений: 19959
Petro123
Eld Hasp,
Почему выделенный объект не сделать свойство через номер, индекс, айдишник?
А зачем его потом разыскивать опять в коллекции, если можно взять непосредственно из свойства?
30 ноя 18, 19:32    [21750707]     Ответить | Цитировать Сообщить модератору
 Re: DataContext биндинг.  [new]
Eld Hasp
Member

Откуда:
Сообщений: 178
После исправления Equals основной проект тоже работает как надо.
Спасибо за помощь!
30 ноя 18, 19:49    [21750720]     Ответить | Цитировать Сообщить модератору
 Re: DataContext биндинг.  [new]
Eld Hasp
Member

Откуда:
Сообщений: 178
Petro123
Eld Hasp,
Почему выделенный объект не сделать свойство через номер, индекс, айдишник?
Shocker.Pro
Petro123
Eld Hasp,
Почему выделенный объект не сделать свойство через номер, индекс, айдишник?
А зачем его потом разыскивать опять в коллекции, если можно взять непосредственно из свойства?

Я не разыскивал его. У меня для редактирования создавалась копия объекта. А перед выходом из редактирования я проверял через Equals были или нет изменения, чтобы сохранить их.
30 ноя 18, 19:53    [21750723]     Ответить | Цитировать Сообщить модератору
 Re: DataContext биндинг.  [new]
Eld Hasp
Member

Откуда:
Сообщений: 178
Shocker.Pro
Eld Hasp
В XAML объекты на по адресу, а через этот метод идентифицируются?
Возможно, это особенность работы SelectedItem, ибо там коллекция, а какой-нибудь FirstOrDefault будет искать через Equals, я в общем, глубоко не стал копать.
Так или иначе, с целью проверки измененных полей переопределять Equals я бы не стал, потому что это много на что влияет, в частности, как раз на Linq-операции.
Но копия у меня даже не входила в коллекцию. Она у меня создавалась отдельно, только на время редактирования и после него должна была отправляться в мусор.
Даже привязка параметра в команде кнопки уже возвращала не тот объект.
В дебагере же все значения полей VM показывало верно. Влияло именно на привязки в XAML.
30 ноя 18, 20:22    [21750746]     Ответить | Цитировать Сообщить модератору
 Re: DataContext биндинг.  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 37082
Shocker.Pro
А зачем его потом разыскивать
это взять из коллекции по индексу?
Коллекция же рядом.
30 ноя 18, 20:25    [21750748]     Ответить | Цитировать Сообщить модератору
 Re: DataContext биндинг.  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 37082
Eld Hasp
перед выходом из редактирования я проверял через Equals были или нет изменения, чтобы сохранить их.
если есть ORM, DAL то это там делается.
30 ноя 18, 20:28    [21750751]     Ответить | Цитировать Сообщить модератору
 Re: DataContext биндинг.  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 37082
Eld Hasp
А перед выходом из редактирования я проверял через Equals были или нет изменения,
еще можно флаг bool поставить и взводить при любом редактировании.
Кроме того, другой юзверь поменял, а этот сохраняет СТАРЫЙ объект.
Что делаем?
30 ноя 18, 20:33    [21750756]     Ответить | Цитировать Сообщить модератору
 Re: DataContext биндинг.  [new]
Eld Hasp
Member

Откуда:
Сообщений: 178
Petro123
Eld Hasp
А перед выходом из редактирования я проверял через Equals были или нет изменения,
еще можно флаг bool поставить и взводить при любом редактировании.
Кроме того, другой юзверь поменял, а этот сохраняет СТАРЫЙ объект.
Что делаем?
Это учебный однопользовательский проект. Без БД. Данные из XML. Можно разные методы определения модификация создать. Но здесь было проще так. Но столкнулся с неожиданным (для меня) поведением привязок. Переделал. Сейчас работает.
Но причину такой работы привязок так и не понял. Буду разбираться.
30 ноя 18, 20:45    [21750767]     Ответить | Цитировать Сообщить модератору
 Re: DataContext биндинг.  [new]
Eld Hasp
Member

Откуда:
Сообщений: 178
Petro123
Eld Hasp
перед выходом из редактирования я проверял через Equals были или нет изменения, чтобы сохранить их.
если есть ORM, DAL то это там делается.
Не совсем. В данном случае это не относится к данным. Это копия объекта выделенного в View, то есть уровень VM. А ORM, DAL - это уровень модели.
30 ноя 18, 20:49    [21750769]     Ответить | Цитировать Сообщить модератору
 Re: DataContext биндинг.  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 37082
Eld Hasp
Без БД
теперь вспомнил тебя).
ОК
30 ноя 18, 21:00    [21750775]     Ответить | Цитировать Сообщить модератору
 Re: DataContext биндинг.  [new]
Eld Hasp
Member

Откуда:
Сообщений: 178
Petro123
Eld Hasp
Без БД
теперь вспомнил тебя).
ОК
Но а я и не забывал!
30 ноя 18, 22:32    [21750807]     Ответить | Цитировать Сообщить модератору
 Re: DataContext биндинг.  [new]
Shocker.Pro
Member

Откуда: ->|<- :адуктО
Сообщений: 19959
Petro123
это взять из коллекции по индексу?
Зачем вообще что-то брать, это ведь подразумевает код. А так ты пишешь мастер-деталь декларативно.
1 дек 18, 00:05    [21750849]     Ответить | Цитировать Сообщить модератору
 Re: DataContext биндинг.  [new]
Petro123
Member

Откуда: Загрузочный сектор Москвы (AutoPOI.ru)
Сообщений: 37082
Shocker.Pro
Petro123
это взять из коллекции по индексу?
Зачем вообще что-то брать, это ведь подразумевает код. А так ты пишешь мастер-деталь декларативно.
тут я не увере что лучше.
Я привык считать что клиент нечто удаленное как в веб.
Поэтому пересылать туда обратно целиком классы расточительно.
Хотя десктоп другая парадигма.
В веб выбранный объект так и будет на клиенте в js).
Да. Декларативность, и есть над чем подумать.
1 дек 18, 09:01    [21750908]     Ответить | Цитировать Сообщить модератору
 Re: DataContext биндинг.  [new]
Shocker.Pro
Member

Откуда: ->|<- :адуктО
Сообщений: 19959
Petro123
тут я не увере что лучше.
Я привык считать что клиент нечто удаленное как в веб.
Поэтому пересылать туда обратно целиком классы расточительно.
У меня сейчас в тонком WPF-клиенте так: пересылается только то, что нужно для отображения в списке (например Name), а все, что нужно для отображения детали - в свойстве, упаковано в асинхронный ленивый контейнер. То есть, когда юзер щелкает по элементу списка, в детали появляется спиннер и через некоторое время деталь. Таким образом, сама форма мастер-деталь остается декларативной, но лишние данные не тянутся на клиент.
1 дек 18, 10:30    [21750923]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: 1 2      [все]
Все форумы / WPF, Silverlight Ответить