Skip to content

Commit

Permalink
ExDM Add documentation to the selected parts of the code #369
Browse files Browse the repository at this point in the history
- working on the XAML section
  • Loading branch information
mpostol committed Jul 5, 2024
1 parent a3b7d02 commit 68925a3
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 39 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
68 changes: 34 additions & 34 deletions ExDataManagement/GraphicalData/GraphicalData.View/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,40 +7,40 @@
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="Auto">
<Window.DataContext>
<vm:MainViewModel />
<vm:MainViewModel />
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="4*" />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<ListBox ItemsSource="{Binding Users}" SelectedItem="{Binding CurrentUser}" Grid.Column="0" Grid.Row="0">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Label Content="{Binding Name}" />
<CheckBox VerticalAlignment="Center" IsChecked="{Binding Active}" IsEnabled="False" />
<Label Content="{Binding Age}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Grid Grid.Column="1" Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBox Text="{Binding CurrentUser.Name}" Grid.Column="0" Grid.Row="0" />
<TextBox Text="{Binding CurrentUser.Age}" Grid.Column="0" Grid.Row="1" />
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="4*" />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<ListBox ItemsSource="{Binding Users}" SelectedItem="{Binding CurrentUser}" Grid.Column="0" Grid.Row="0">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Label Content="{Binding Name}" />
<CheckBox VerticalAlignment="Center" IsChecked="{Binding Active}" IsEnabled="False" />
<Label Content="{Binding Age}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Grid Grid.Column="1" Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBox Text="{Binding CurrentUser.Name}" Grid.Column="0" Grid.Row="0" />
<TextBox Text="{Binding CurrentUser.Age}" Grid.Column="0" Grid.Row="1" />
</Grid>
<Button Content="Click the button to load new data" Grid.Column="0" Grid.Row="1" Command="{Binding FetchDataCommend}" />
<Button Command="{Binding ShowTreeViewMainWindowCommend}" Content="Click the button to display TreeView Window" Grid.Column="0" Grid.Row="2" Width="Auto" />
<Button Content="Click to display text below" Grid.Column="1" Grid.Row="1" Command="{Binding DisplayTextCommand}" />
<TextBox Text="{Binding ActionText}" Grid.Column="1" Grid.Row="2" TextWrapping="Wrap" />
</Grid>
<Button Content="Click the button to load new data" Grid.Column="0" Grid.Row="1" Command="{Binding FetchDataCommend}" />
<Button Content="Click the button to display TreeView Window" Grid.Column="0" Grid.Row="2" Width="Auto" Command="{Binding ShowTreeViewMainWindowCommend}" />
<Button Content="Click to display text below" Grid.Column="1" Grid.Row="1" Command="{Binding DisplayTextCommand}" />
<TextBox Text="{Binding ActionText}" Grid.Column="1" Grid.Row="2" TextWrapping="Wrap" />
</Grid>
</Window>
14 changes: 9 additions & 5 deletions ExDataManagement/GraphicalData/README.XAML.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,21 +155,23 @@ The [AttachedProperty][AttachedProperty] class definition simulates this reflect

### 6.4. INotifyPropertyChange

Using properties defined in the `Binding` type, we can parameterize the transfer process and, for example, limit its direction. Operations described by `XAML` text are performed once at the beginning of the program when the MainWindow instance is created. Therefore, we cannot here specify the point in time when this transfer should be carried out. To determine the point in time when an instance of the `Binding` type should trigger this transfer, let's look at the structure of the [ActionText][ActionText] property in the `MainViewWindow` type. Here we see that the setter performs two additional methods. In the context of the main problem, the `RaisePropertyChanged` method is invoked. This method activates an event required to implement the `INotifyPropertyChanged` interface.
Using properties defined in the `Binding` type, we can parameterize the transfer process and, for example, limit its direction. Operations described by the `XAML` text are performed once at the beginning of the program when the `MainWindow` instance is created. Therefore, we cannot here specify the point in time when this transfer should be carried out. To determine the point in time when an instance of the `Binding` type should trigger this transfer, let's look at the structure of the [ActionText][ActionText] property in the [MainViewWindow][MainViewWindow] type. Here we see that the setter (used to update the current value) performs two additional methods. In the context of the main problem, the `RaisePropertyChanged` method is invoked. This method activates the `PropertyChanged` event required to implement the `INotifyPropertyChanged` interface.

``` CSharp
public event PropertyChangedEventHandler PropertyChanged;
```

This event is used by objects of the `Binding` class to invoke the current value transfer. By activating this event, we call methods whose delegates have been added to the event. If the class does not implement this interface or the activation of the `PropertyChanged` event required by the mentioned interface does not occur, the new value will not be passed to and will not be refreshed on the screen - the screen will be static.
This event is used by objects of the `Binding` class to invoke the current value transfer. As a result of activating this event, we call methods whose delegates have been added to the `PropertyChanged` event required by the mentioned interface. If the class does not implement this interface or the activation of the `PropertyChanged` event does not occur, the new value assigned to a property will not be pulled and transferred to the bonded property of a control. Finally, the screen will not be refreshed - the screen will be static.

It is typical communication where the `MainViewWindow` instance notifies about the selected value change and the `MainWindow` instance pulls a new value and displays it. In this kind of communication the `MainViewWindow` has a publisher role and the `MainWindow` is the subscriber. It is worth stressing that communication is a run-time activity. It is initiated in the opposite direction compared with the compile time types relationship. Hence we can recognize it as an inversion of control or a callback communication method.
It is typical communication where the [MainViewWindow][MainViewWindow] instance notifies about the selected value change and the `MainWindow` instance pulls a new value and displays it. In this kind of communication the [MainViewWindow][MainViewWindow] has a publisher role and the `MainWindow` is the subscriber. It is worth stressing that communication is a run-time activity. It is initiated in the opposite direction compared with the compile time types relationship. Hence we can recognize it as an inversion of control or a callback communication method.

### 6.5. ICommand

The analysis of the previous examples shows the screen content synchronization mechanism with the property values change ​​of classes dedicated to providing data for the GUI. Now we need to explain the sequence of operations carried out as a consequence of issuing a command by the user interface, e.g. clicking on the on-screen key - `Button`. We have an example here, and its `Command` property has been associated, as before, with something with the identifier [ShowTreeViewMainWindowCommend][ShowTreeView]. Using navigation in Visual Studio, we can go to the definition of this identifier and notice that it is again a property from the `MainViewWindow` class, but of the `ICommand` type. This time, this binding is not used to copy the property value but to convert a key click on the screen, e.g. using a mouse, into calling the `Execute` operation, which is defined in the `ICommand` interface and must be implemented in the class that serves to create an object and assign a reference to it into this property.
The analysis of the previous examples shows the screen content synchronization mechanism with the property values change ​​of classes dedicated to providing data for the GUI. Now we need to explain the sequence of operations carried out as a consequence of issuing a command by the user interface, e.g. clicking on the on-screen key - `Button`. We have an example here, and its `Command` property has been associated, as before, with something with the identifier [ShowTreeViewMainWindowCommend][ShowTreeView]. Using navigation in Visual Studio, we can go to the definition of this identifier and notice that it is again a property from the [MainViewWindow][MainViewWindow] class, but of the `ICommand` type. This time, this binding is not used to copy the property value but to convert a key click on the screen, e.g. using a mouse, into calling the `Execute` operation, which is defined in the `ICommand` interface and must be implemented in the class that serves to create an object and assign a reference to it into this property.

For the sake of simplicity, the `ICommand` interface is implemented by a helper class called [RelayCommand][RelayCommand]. In the constructor of this class, you should place a delegate to the method to be called as a result of the command execution. The second constructor is helpful in dynamically changing the state of a button on the screen. This can block future events, i.e. realize a state machine. And this is exactly the scenario implemented in the examined example program. Please note the `RaiseCanExecuteChanged` method omitted in the previous explanation.
For the sake of simplicity, the `ICommand` interface is implemented by a helper class called [RelayCommand][RelayCommand]. In the constructor of this class, you should place a delegate to the method to be called as a result of the command execution. The second constructor is helpful in dynamically changing the state of a button on the screen. This can block future events, i.e. realize a state machine. And this is exactly the scenario implemented in the examined example program. Please note the [RaiseCanExecuteChanged][RaiseCanExecuteChanged] method omitted in the previous explanation.

![Show Tree View](.Media/ShowTreeView.gif)

## 7. See also

Expand All @@ -189,3 +191,5 @@ For the sake of simplicity, the `ICommand` interface is implemented by a helper
[InitializeComponent]: https://github.com/mpostol/TP/blob/5.13-India/ExDataManagement/GraphicalData/GraphicalData.View/MainWindow.xaml.cs#L23-L26
[MainWindow]: https://github.com/mpostol/TP/blob/5.13-India/ExDataManagement/GraphicalData/GraphicalData.View/MainWindow.xaml.cs#L21-L34
[App]: https://github.com/mpostol/TP/blob/5.13-India/ExDataManagement/GraphicalData/GraphicalData.View/App.xaml#L1-L7
[MainViewWindow]: https://github.com/mpostol/TP/blob//5.13-India/ExDataManagement/GraphicalData/GraphicalData.ViewModel/MainViewModel.cs#L20-L150
[RaiseCanExecuteChanged]: https://github.com/mpostol/TP/blob/5.13-India/ExDataManagement/GraphicalData/GraphicalData.ViewModel/MVVMLight/RelayCommand.cs#L88-L91

0 comments on commit 68925a3

Please sign in to comment.