0

我正在使用带有动态标志 canExecute 的第一个命令。

我有我的保存命令,只有当用户进行一些数据更改时才必须启用它。

我正在考虑在制作模组时绑定一个动作,但我得到了错误,也许这不是正确的方法。

这是我的 xaml(如您所见,我的所有字段都在布局控件中):

            <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>

这是我的 MainWindowVIewModel,我在其中定义了命令和 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");
}

当我填充我的 observableColletion 时,我在绑定的用户控件中更改数据,我有:

ListaImpianti.CollectionChanged += (s, e) => EnableSave(e);

ListaImpianti 以这种方式绑定到 xaml:

<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 定义为:

 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); }

但是永远不会调用启用保存..为什么?

皮耶罗

4

2 回答 2

0

通常,如果您想在属性更改时完成某些事情,您会为 PropertyChangedEvent 添加一个侦听器。当有许多属性时,这不会改变,这是一个可能的实现:为包含要监视的属性的 viewModel 的 PropertyChanged 事件注册一个侦听器,并检查更改的属性的名称是否与您要监视的属性之一匹配。如果是这样,请启用保存按钮。

MainWindowViewModel()
{
  otherVewModel.PropertyChanged += ( s, e ) => EnableSaveIfCertainPropertiesChange( e );
}

List<string> propertiesTriggeringEnableSave = new List<string> {
  "IDTTS", "REMOTO", "TIPOCONN" //and so on
};

void EnableSaveIfCertainPropertiesChange( PropertyChangedEventArgs e )
{
  if( propertiesTriggeringEnableSave.Contains( e.PropertyName ) )
    SaveButtonEnabled = true;
}

public bool SaveButtonEnabled
{
  get{ return saveButtonEnabled; }
  set
  {
    saveButtonEnabled = value;
    base.RaisePropertyChangedEvent("SaveButtonEnabled");
  }
}
bool saveButtonEnabled

还有一些一般准则:注意我将 SaveButtonEnabled 更改为它在 mvvm 中的常用方式:这比您现在使用的更好,因为您不必重复(容易出错)RaisePropertyChangedEvent 行。此外,我不会为命令的延迟初始化而烦恼,边际(如果有的话)性能增益会产生更丑陋的代码。如果您的命令在构造函数中初始化,我认为代码会更短且更具可读性

MainViewModel()
{
  SaveCommand = new DelegateCommand( Save, CanSave );
}

public ICommand SaveCommand{ get; private set; }
于 2014-09-22T07:06:06.667 回答
0

如果用户改变了一些东西,viewmodel 会知道的,对吧?对我来说很清楚,SaveButtonEnabled应该由视图模型本身更改标志,而不是通过绑定到视图的任何命令。

例如,如果用户更改SERMATIC属性,则该属性的设置器是您必须在必要时更改标志的地方。

旁注:将这些base.RaisePropertyChangedEvent("SaveButtonEnabled")片段移动到SaveButtonEnabled属性的设置器。

于 2014-09-22T08:22:43.723 回答