I'm working with my first command with a dynamic flag canExecute.
I have my save command, that it must enabled only when user makes some data changes.
I was thinking about binding an action when the mods are made, but I get errors, maybe this isn't the right way.
This is my xaml (as you can see, all my fields are in a layout control):
<dxlc:LayoutGroup Header="Configurazione tecnica" View="GroupBox" Orientation="Vertical">
<dxlc:LayoutItem Label="Tipo sistema">
<dxe:ComboBoxEdit IsTextEditable="False" EditValue="{Binding IDTTS}" ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}},Path=DataContext.tts}" />
</dxlc:LayoutItem>
<dxlc:LayoutItem Label="Locazione">
<!--<dxe:ComboBoxEdit EditValue="{Binding REMOTO}" ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}},Path=DataContext.locations}" />-->
<StackPanel Margin="0" Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Left">
<RadioButton x:Name="rd_LOCALE" Content="{DynamicResource Locale}" Margin="10,0,0,0" VerticalAlignment="Center" GroupName="Location" IsChecked="True" Panel.ZIndex="9" TabIndex="10" />
<RadioButton Content="{DynamicResource Remoto}" Margin="10,0,6,0" x:Name="rd_REMOTO" Tag="PRISMA" VerticalAlignment="Center" IsChecked="{Binding REMOTO}" GroupName="Location" Panel.ZIndex="10" TabIndex="11" />
</StackPanel>
</dxlc:LayoutItem>
<dxlc:LayoutItem Label="Tipo di connessione">
<!--<dxe:ComboBoxEdit EditValue="{Binding TIPOCONN}" />-->
<StackPanel Margin="0" Orientation="Horizontal" VerticalAlignment="Center">
<RadioButton Content="{DynamicResource Terminale}" Margin="10,0,0,0" x:Name="rd_TIPOCONN" Tag="PRISMA" VerticalAlignment="Center" GroupName="TipoConn" IsChecked="True" Panel.ZIndex="11" TabIndex="12" />
<RadioButton x:Name="rd_SLAVE" Content="Slave" Margin="10,0,6,0" Tag="PRISMA" VerticalAlignment="Center" IsChecked="{Binding TIPOCONN}" GroupName="TipoConn" Panel.ZIndex="12" TabIndex="13" />
</StackPanel>
</dxlc:LayoutItem>
</dxlc:LayoutGroup>
<dxlc:LayoutGroup Header="Centralina STK" View="GroupBox" Orientation="Vertical">
<dxlc:LayoutItem >
<!--<dxe:ComboBoxEdit EditValue="{Binding SERMATIC}" />-->
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,6">
<RadioButton x:Name="rd_sermatic" Content="{DynamicResource SI}" Margin="10,0,0,0" Tag="PRISMA" VerticalAlignment="Center" Width="100" HorizontalAlignment="Left" IsChecked="{Binding SERMATIC}" GroupName="stk" Panel.ZIndex="13" TabIndex="14" />
<RadioButton x:Name="rd_sermaticNO" Content="{DynamicResource NO}" Margin="10,0,0,0" Tag="PRISMA" VerticalAlignment="Center" Width="100" HorizontalAlignment="Left" GroupName="stk" IsChecked="True" Panel.ZIndex="14" TabIndex="15" />
</StackPanel>
</dxlc:LayoutItem>
<dxlc:LayoutItem >
<!--<dxe:ComboBoxEdit EditValue="{Binding SERMATICCOM}"/>-->
<UniformGrid Rows="1" Columns="2" DockPanel.Dock="Top" Margin="4,0,4,4" IsEnabled="{Binding IsChecked, ElementName=rd_sermatic}">
<TextBlock Margin="0" TextWrapping="Wrap" Text="{DynamicResource PortaCOM}" TextAlignment="Right" VerticalAlignment="Center" HorizontalAlignment="Right"/>
<ComboBox x:Name="cmb_SERMATICCOM" Height="23" Margin="10,2,0,0" Panel.ZIndex="15" TabIndex="16">
<ComboBoxItem Content="----" />
<ComboBoxItem Content="COM1" />
<ComboBoxItem Content="COM2" />
<ComboBoxItem Content="COM3" />
<ComboBoxItem Content="COM4" />
<ComboBoxItem Content="COM5" />
<ComboBoxItem Content="COM6" />
<ComboBoxItem Content="COM7" />
<ComboBoxItem Content="COM8" />
</ComboBox>
</UniformGrid>
</dxlc:LayoutItem>
</dxlc:LayoutGroup>
</dxlc:LayoutControl>
And this is my MainWindowVIewModel, where I define the command and the canExceute:
private bool CanSave()
{
return SaveButtonEnabled;
}
public ICommand SaveCommand { get; private set; }
void EnableSave(NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Replace)
SaveButtonEnabled = true;
}
private bool p_saveButtonEnabled=false;
public bool SaveButtonEnabled
{
get{ return p_saveButtonEnabled; }
set
{
p_saveButtonEnabled = value;
base.RaisePropertyChangedEvent("SaveButtonEnabled");
}
}
private void SaveData()
{
MainWindow.dbContext.SaveChanges();
SaveButtonEnabled = false;
//base.RaisePropertyChangedEvent("SaveButtonEnabled");
}
And when I populated my observableColletion, where I change data in the binded user control, I have:
ListaImpianti.CollectionChanged += (s, e) => EnableSave(e);
ListaImpianti is binded to the xaml in this way:
<DockPanel Grid.Row="1" Margin="0,60,0,0">
<dxg:GridControl x:Name="lst1" ItemsSource="{Binding ListaImpianti}" EnableSmartColumnsGeneration="True" FilterCriteria="{Binding FilterCriteria, ElementName=searchControl}" MaxHeight="500" Height="266" VerticalAlignment="Top" Margin="0,-27,0,0" Width="332" ShowBorder="False">
<dxg:GridControl.Columns>
<dxg:GridColumn x:Name="CODICE" Binding="{Binding CODICE}" FieldName="CODICE"/>
<dxg:GridColumn x:Name="NOME" Binding="{Binding NOME}" FieldName="NOME"/>
</dxg:GridControl.Columns>
<dxg:GridControl.View>
<dxg:TableView AllowPerPixelScrolling="True" AllowEditing="False" ShowGroupPanel="False" ShowFilterPanelMode="Never" />
</dxg:GridControl.View>
</dxg:GridControl>
</DockPanel>
ListaImpianti is defined as:
public ObservableCollection<TabImpianti> ListaImpianti
{
get { return p_ListaImpianti; }
set
{
p_ListaImpianti = value;
base.RaisePropertyChangedEvent("ListaImpianti");
}
}
[...]
p_ListaImpianti = new ObservableCollection<TabImpianti>();
var query2 = (from r in MainWindow.dbContext.TabImpianti select r);
foreach (TabImpianti ti in query2) { p_ListaImpianti.Add(ti); }
But enable save is never called.. why?
Piero
If the user changes something, the viewmodel will know it, right? To me is clear that the flag SaveButtonEnabled
should be changed by the viewmodel itself, not by any command bound to the view.
For example, if user changes SERMATIC
property, the setter of that property is where you have to change the flag if necesary.
Side note: move those base.RaisePropertyChangedEvent("SaveButtonEnabled")
snippets to the setter of the SaveButtonEnabled
property.