Эксперт .NET
4341 / 2003 / 387
Регистрация: 27.03.2010
Сообщений: 5,455
Записей в блоге: 1
1

При изменении Вью Модели в окне не отображаются изменения, но фактически применяются к вью модели

04.07.2014, 09:17. Показов 775. Ответов 0
Метки нет (Все метки)

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

Было:
UserControl, в нём много элементов и привязана прям в XAML вью модель
Например:
XML
1
2
3
  <UserControl.DataContext>
    <viewModel:SomeParamsViewModel />
  </UserControl.DataContext>
И потом этот контрол помещался в окно. НА контроле есть кнопки ОК и Отмена. При нажатии ОК вызывался определённый обработчик, который закрывал окно.

Сейчас же, я разделил основной UserControl на более мелкие чкасти и стало так:

Несколько UserControl'ов вложены в один UserControl и уже он в окно. Теперь же данные, которые я меняю в коде не отображаются. Не понимаю в чём причина.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
        public RelayCommand<object> OpenTestWindowCommand
        {
            get
            {
                return _openTestWindowCommand ?? (_openTestWindowCommand = new RelayCommand<object>(
                    obj =>
                    {
                        //TestViewModel ctvm = new TestViewModel();
                        
                        TestWindow window = new TestWindow();
                        window.SettingsApplied += window_SettingsApplied;
                        window.Show();
 
                        TestViewModel ctvm = (TestViewModel)window.DataContext;
                        ctvm.DoserParams.DiscretenessMapping = 100;
                        ctvm.DoserParams.BatcherAccuracy = 555;
                        ctvm.DoserParams.BearingCapacity = 777;
 
                        window.Closing += (sender, args) =>
                        {
                            var vm = ((TestWindow)sender).DataContext;
                            MessageBox.Show(vm.ToString());
                        };
           
                        Task.Factory.StartNew(() =>
                        {
                            Thread.Sleep(2000);
                        }).ContinueWith(task =>
                        {
                            ctvm.DoserParams.BatcherAccuracy = 33;
                            ctvm.DoserParams.BearingCapacity = 22;
                        }, TaskScheduler.FromCurrentSynchronizationContext());
                    }));
            }
        }

Сейчас снова затестил. Данные, которые я меняю в окне вообще не применяются. Биндинги прописаны точно нормально.

Вот код одного из юзер контролов
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<UserControl x:Class="XXX.Controls.Settings.Parts.TimeToError.View.TimeToErrorControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:uiElements="clr-namespace:XXX.Controls.UIElements"
             d:DesignHeight="100"
             d:DesignWidth="400"
             mc:Ignorable="d">
 
  <Grid>
    <GroupBox Header="Время до возникновения ошибки"
              Style="{DynamicResource GroupBoxBeveledСornersStyle}">
      <Grid>
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="{StaticResource TextColumnDefaultWidthKey}" />
          <ColumnDefinition Width="{StaticResource NumericUDColumnDefaultWidthKey}" />
          <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto" />
          <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
 
        <TextBlock Grid.Row="0"
                   Grid.Column="0"
                   Style="{DynamicResource TextBlockSettingsStyle}"
                   Text="Не открылся" />
        <TextBlock Grid.Row="1"
                   Grid.Column="0"
                   Style="{DynamicResource TextBlockSettingsStyle}"
                   Text="Не закрылся" />
 
        <uiElements:NumericUpDown Grid.Row="0"
                                  Grid.Column="1"
                                  VerticalAlignment="Center"
                                  Maximum="60000"
                                  Value="{Binding ElapsedTimeBeforeTheErrorAsNotOpened,
                                                  Mode=TwoWay,
                                                  UpdateSourceTrigger=PropertyChanged}" />
        <uiElements:NumericUpDown Grid.Row="1"
                                  Grid.Column="1"
                                  VerticalAlignment="Center"
                                  Maximum="60000"
                                  Value="{Binding ElapsedTimeBeforeTheErrorAsNotClosed,
                                                  Mode=TwoWay,
                                                  UpdateSourceTrigger=PropertyChanged}" />
 
        <TextBlock Grid.Row="0"
                   Grid.Column="2"
                   Style="{DynamicResource TextBlockSettingsDefaultStyle}"
                   Text="мс" />
        <TextBlock Grid.Row="1"
                   Grid.Column="2"
                   Style="{DynamicResource TextBlockSettingsDefaultStyle}"
                   Text="мс" />
      </Grid>
    </GroupBox>
 
  </Grid>
</UserControl>

Вот код окна использующего этот контрол:
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<settings:SettingsWindowBase x:Class="Client.Views.TESTS.TestWindow"
                             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                             xmlns:View="clr-namespace:XXX.Controls.Settings.Parts.DoserParams.View;assembly=XXX.Controls"
                             xmlns:View1="clr-namespace:XXX.Controls.Settings.Parts.TimeToError.View;assembly=XXX.Controls"
                             xmlns:converters="clr-namespace:Client.Converters"
                             xmlns:settings="clr-namespace:Client.Views.Settings"
                             xmlns:view="clr-namespace:XXX.Controls.Settings.Parts._TEST_CONTROL.View;assembly=XXX.Controls"
                             xmlns:viewModel="clr-namespace:XXX.Controls.Settings.Parts._TEST_CONTROL.ViewModel;assembly=XXX.Controls"
                             x:Name="window"
                             Title="{Binding Title}"
                             TextOptions.TextFormattingMode="Display">
 
  <Window.Resources>
    <converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverterKey" />
  </Window.Resources>
 
  <Window.DataContext>
    <viewModel:TestViewModel />
  </Window.DataContext>
 
  <Window.Style>
    <StaticResource ResourceKey="SettingsWindowStyle" />
  </Window.Style>
 
  <!--<Window.BindingGroup>
    <BindingGroup />
  </Window.BindingGroup>-->
 
  <view:TestUserControl x:Name="SettingsControl" />
 
</settings:SettingsWindowBase>
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
    public class TimeToErrorViewModel : ViewModelBase
    {
        private double _elapsedTimeBeforeTheErrorAsNotOpened;
        private double _elapsedTimeBeforeTheErrorAsNotClosed;
 
        public TimeToErrorViewModel()
        {
            ElapsedTimeBeforeTheErrorAsNotOpened = 20d;
            ElapsedTimeBeforeTheErrorAsNotClosed = 20d;
        }
 
        /// <summary>Время до ошибки "не открылся"</summary>
        public double ElapsedTimeBeforeTheErrorAsNotOpened
        {
            get { return _elapsedTimeBeforeTheErrorAsNotOpened; }
            set
            {
                _elapsedTimeBeforeTheErrorAsNotOpened = value;
                RaisePropertyChanged("ElapsedTimeBeforeTheErrorAsNotOpened");
            }
        }
 
        /// <summary>Время до ошибки "не закрылся"</summary>
        public double ElapsedTimeBeforeTheErrorAsNotClosed
        {
            get { return _elapsedTimeBeforeTheErrorAsNotClosed; }
            set
            {
                _elapsedTimeBeforeTheErrorAsNotClosed = value;
                RaisePropertyChanged("ElapsedTimeBeforeTheErrorAsNotClosed");
            }
        }
    }
Добавлено через 2 минуты
Ещё внутри основного UserControl'a (который содержит в себе 2 других) такой код:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    /// <summary>
    /// Логика взаимодействия для TestUserControl.xaml
    /// </summary>
    public partial class TestUserControl : UserControlBase
    {
        public TestUserControl()
        {
            InitializeComponent();
            (new DragableWindowBehaviour()).Register(this);
            (new ClosableWindowBehaviour()).Register(this);
        }
 
        public void Connect(int connectionId, object target)
        {
            
        }
 
    }
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
    /// <summary>
    /// Поведение, взаимодействует с кнопками закрытия окна ОК и Отмена, инициирует вызов событий 
    /// Нажатий по этим кнопками и событие применения настроек
    /// </summary>
    sealed class ClosableWindowBehaviour : UserControlBehaviourBase
    {
        private Window _window;
 
        protected override void Control_Loaded(object sender, RoutedEventArgs e)
        {
            var control = (UserControlBase)sender;
            var cancelButton = (Button)LogicalTreeHelper.FindLogicalNode(control, "CancelButton");
            var okButton = (Button)LogicalTreeHelper.FindLogicalNode(control, "OkButton");
 
            _window = FindWindowAsParent(control);
            if (_window != null)
            {
                _window.Closed += (o, args) =>
                {
                    if (_window.Owner != null && _window.Owner.OwnedWindows.Count < 1)
                    {
                        _window.Owner.Activate();
                        _window.Owner = null;
                    }
                };
            }
 
            Debug.Assert(cancelButton != null, "closeButton != null");
            cancelButton.Click += (o, args) =>
            {
                if (_window != null)
                {
                    try
                    {
                        _window.DialogResult = false;
                    }
                    catch (InvalidOperationException)
                    {
                    }
                    _window.Close();
                }
                //control.BindingGroup.CancelEdit();
                control.OnCancelButtonClicked(args);
            };
 
            Debug.Assert(okButton != null, "okButton != null");
            okButton.Click += (o, args) =>
            {
                if (_window != null)
                {
                    try
                    {
                        _window.DialogResult = true;
                    }
                    catch (InvalidOperationException)
                    {
                    }
                    _window.Close();
                }
                //control.BindingGroup.CommitEdit();
                control.OnOkButtonClicked(args);
                control.OnSettingsApplied(new SettingsEventArgs(control.DataContext));
            };
        }
    }
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
    abstract class UserControlBehaviourBase
    {
        public void Register(UserControl control)
        {
            if (control.IsLoaded)
                Debug.Fail("UserControl был загружен (control.IsLoaded == true) ранее, чем подписался на обработчик события его загрузки (control.Loaded += Control_Loaded)");
            control.Loaded += Control_Loaded;
        }
 
        protected abstract void Control_Loaded(object sender, RoutedEventArgs e);
 
        protected virtual Window FindWindowAsParent(UserControl control)
        {
            if (control.Parent is Window)
            {
                return (Window)control.Parent;
            }
            if (control.Parent is Border)
            {
                return ((Border)control.Parent).Parent as Window;
            }
            if (control.Parent is Grid)
            {
                return ((Grid)control.Parent).Parent as Window;
            }
            return null;
        }
 
        protected UIElement FindContentControlInLogicalTreeByName(string uiElementName, ContentControl control)
        {
            var uiElement = (UIElement)LogicalTreeHelper.FindLogicalNode(control, uiElementName);
            if (uiElement == null)
            {
                Debug.Fail(string.Format("В {0} элемент {1} не найден", control.Name, uiElementName));
            }
            return uiElement;
        }
    }
Добавлено через 4 минуты
Вот код основного окна:
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<view2:UserControlBase x:Class="XXX.Controls.Settings.Parts._TEST_CONTROL.View.TestUserControl"
                       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                       xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                       xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                       xmlns:view="clr-namespace:XXX.Controls.Settings.Parts.TimeToError.View"
                       xmlns:view1="clr-namespace:XXX.Controls.Settings.Parts.DoserParams.View"
                       xmlns:view2="clr-namespace:XXX.Controls.Settings.View"
                       xmlns:view3="clr-namespace:XXX.Controls.Settings.Parts._TEST_CONTROL.View"
                       xmlns:viewModel="clr-namespace:XXX.Controls.Settings.Parts._TEST_CONTROL.ViewModel"
                       mc:Ignorable="d">
 
  <UserControl.DataContext>
    <viewModel:TestViewModel />
  </UserControl.DataContext>
 
  <GroupBox x:Name="RootGroupBox"
            Margin="4,0,9,9"
            Header="{Binding Title}"
            Style="{StaticResource GroupBoxRightAnglesStyle}">
    <Grid x:Name="LayoutRoot">
      <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto"
                       MinHeight="50" />
      </Grid.RowDefinitions>
 
      <view1:DoserParamsControl Grid.Row="0"
                                DataContext="{Binding Path=DataContext.DoserParams,
                                                      Mode=TwoWay,
                                                      RelativeSource={RelativeSource FindAncestor,
                                                                                     AncestorType={x:Type view2:UserControlBase}}}" />
      <view:TimeToErrorControl Grid.Row="1"
                               DataContext="{Binding Path=DataContext.TimeToError,
                                                     Mode=TwoWay,
                                                     RelativeSource={RelativeSource FindAncestor,
                                                                                    AncestorType={x:Type view2:UserControlBase}}}" />
      <Button x:Name="OkButton"
              Grid.Row="2"
              Width="109"
              Margin="23,0,0,10"
              HorizontalAlignment="Left"
              VerticalAlignment="Bottom"
              Content="ОК"
              Style="{DynamicResource ButtonMainStyle}" />
 
      <Button x:Name="CancelButton"
              Grid.Row="2"
              Width="109"
              Margin="0,0,23,10"
              HorizontalAlignment="Right"
              VerticalAlignment="Bottom"
              Content="Отмена"
              IsCancel="True"
              Style="{DynamicResource ButtonMainStyle}" />
 
    </Grid>
  </GroupBox>
</view2:UserControlBase>
Добавлено через 20 минут
Заметил, что в основном UserControl'е в XAML в DataContext задаётся та же вью модель, чт о и в дата контексте окна, закомментировал, всё заработало

Добавлено через 1 минуту
Другими словами, у вложенного контрола был сво объект в дата контексте, который никак не взаимодействовал с дата контекстом окна, я так это понял.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
04.07.2014, 09:17
Ответы с готовыми решениями:

DataGridColumn не становится невидимым при бандинге к вью модели
В чём причина? Вот добавляю во вью модель свойство string Title и ради теста биндю к текстблоку,...

Ошибка при работе с приватной вью из Ls
Имеется приватная (SDPOFU) папка, служащая для поиска документов в базе. Папка имеет действие, в...

При выборе из Ad модели выбрать по кол-ву в связанной модели ad_images
Всем привет В laravel 6 с фильтром из таблицы ads и хочу установить условие чтобы возвращались...

Обновление модели QStandardItemModel при изменении значения одного из элементов
Здравствуйте, есть модель заполненная значениями, которая впоследствии выводится посредством...

0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
04.07.2014, 09:17

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Паттерн MVVM. Обновление вида при изменении значений параметров модели
Добрый день! Очень простой пример MVVM - книга контактов. Модель - единственный класс Person. ...

Не происходят изменения в БД при использовании модели QSqlRelationalTableModel
Здравствуйте! Возникла такая проблема: при выводе таблицы из БД в QTableView, используя модель...

EF 6.4 игнорирует указанные в модели изменения при перестроении миграции
У меня вот такая модель: public class FileHash { public Guid UID_File { get;...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
1
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.