2016-10-05 64 views
0

我有一個WPF應用程序,它不會讓我點擊按鈕,直到有點時間過去,但是這種行爲是隨機的,只發生在某些時間。大部分時間窗口呈現,我可以立即點擊說按鈕。當窗口呈現時,按鈕不可點擊

主窗口:

<views:StatusBox DockPanel.Dock="Left" Visibility="{Binding Editing, Converter={StaticResource BoolToVisibleConverter}}" /> 
</DockPanel> 

用戶控制:

<StackPanel Orientation="Horizontal"> 
    <!--Read Button--> 
    <Button Content="Read " x:Name="ReadBtn"  Command="{Binding ReadCMD}" Padding="10,5" Margin= "10,0" IsEnabled="{Binding ReadEnabled}" /> 

    <!--Save Button--> 
    <Button Content="Save " x:Name="SaveBtn"  Command="{Binding SaveCMD}" Padding="10,5" Margin= "10,0" IsEnabled="{Binding SaveEnabled}" 
      Background="{StaticResource {x:Static SystemColors.ControlLightBrushKey}}"> 
     <Button.Style> 
      <Style TargetType="Button"> 
       <Style.Triggers> 
        <DataTrigger Binding="{Binding IsSaveNeeded}" Value="Yes"> 
         <DataTrigger.EnterActions> 
          <BeginStoryboard x:Name="FlashBackground"> 
           <Storyboard BeginTime="00:00:00" RepeatBehavior="Forever" > 
            <ColorAnimation Storyboard.TargetProperty="Background.Color" Duration="00:00:00.25" AutoReverse="True" To="Red" /> 
           </Storyboard> 
          </BeginStoryboard> 
         </DataTrigger.EnterActions> 

         <DataTrigger.ExitActions> 
          <StopStoryboard BeginStoryboardName="FlashBackground" /> 
         </DataTrigger.ExitActions> 
        </DataTrigger> 
       </Style.Triggers> 
      </Style> 
     </Button.Style> 
    </Button> 

    <!--Load Button--> 
    <Button Content="Load " x:Name="LoadBtn"  Command="{Binding LoadCMD}" Padding="10,5" Margin= "10,0" IsEnabled="{Binding LoadEnabled}" /> 

    <!--Print Button--> 
    <Button Content="Print" x:Name="PrintBtn" Command="{Binding PrintCMD}" Padding="10,5" Margin= "10,0" IsEnabled="{Binding PrintEnabled}" /> 

    <!--Exit Button--> 
    <Button Content="Exit" x:Name="ExitBtn"  Command="{Binding ExitCMD}" Padding="10,5" Margin= "10,0" /> 
</StackPanel> 

視圖模型

private bool _tab1_Selected; 
    public bool tab1_Selected 
    { 
     get 
     { 
      return _tab1_Selected; 
     } 
     set 
     { 
      _tab1_Selected = value; 

      if (value) 
      { 
       CommMode = (byte)PacketType.tab1_DUMP; 

       if (tab1needsSaving) 
       { 
        IsSaveNeeded = SaveNeeded.Yes; 
       } 
       else 
       { 
        IsSaveNeeded = SaveNeeded.No; 
       } 
      } 

      NotifyPropertyChanged("tab1_Selected"); 
      NotifyPropertyChanged("SaveEnabled"); 
      NotifyPropertyChanged("ProgramEnabled"); 
      NotifyPropertyChanged("Editing"); 
     } 
    } 


    private bool _tab2_Selected; 
    public bool tab2_Selected 
    { 
     get 
     { 
      return _tab2_Selected; 
     } 
     set 
     { 
      _tab2_Selected = value; 

      if (value) 
      { 
       CommMode = (byte)PacketType.tab2_DUMP; 

       if (tab2needsSaving) 
       { 
        IsSaveNeeded = SaveNeeded.Yes; 
       } 
       else 
       { 
        IsSaveNeeded = SaveNeeded.No; 
       } 
      } 

      NotifyPropertyChanged("tab2_Selected"); 
      NotifyPropertyChanged("SaveEnabled"); 
      NotifyPropertyChanged("ProgramEnabled"); 
      NotifyPropertyChanged("Editing"); 
     } 
    } 


public bool Editing 
    { 
     get 
     { 
      return tab2_Selected || tab1_Selected; 
     } 
    } 

private bool _saveEnabled; 
    public bool SaveEnabled 
    { 
     get 
     { 
      //return _saveEnabled; 
      return ((tab1_Selected && tab1Data != null && tab1Data.Count > 0) || (tab2_Selected && tab2Data != null && tab2Data.Count > 0) && _saveEnabled); 
     } 
     set 
     { 
      _saveEnabled = value; 
      NotifyPropertyChanged("SaveEnabled"); 
     } 
    } 

private bool _programEnabled; 
    public bool ProgramEnabled 
    { 
     get 
     { 
      //return _saveEnabled; 
      return ((tab1_Selected && tab1Data != null && tab1Data.Count > 0) || (tab2_Selected && tab2Data != null && tab2Data.Count > 0) && _programEnabled); 
     } 
     set 
     { 
      _programEnabled = value; 
      NotifyPropertyChanged("ProgramEnabled"); 
     } 
    } 

命令:

public ICommand ReadCMD  { get; set; } 
    public ICommand SaveCMD  { get; set; } 
    public ICommand LoadCMD  { get; set; } 
    public ICommand ProgramCMD { get; set; } 
    public ICommand PrintCMD { get; set; } 
    public ICommand ExitCMD  { get; set; } 

    // In MainVM constructor 
    ReadCMD = new RelayCommand(ReadSettings); 
    SaveCMD = new RelayCommand(SaveSettings); 
    LoadCMD = new RelayCommand(LoadSettings); 
    ProgramCMD = new RelayCommand(ProgramSettings); 
    PrintCMD = new RelayCommand(PrintSettings); 
    ExitCMD = new RelayCommand(ExitProgram); 

繼電器的命令類:

public class RelayCommand : ICommand 
{ 
    private Action<object> execute; 

    private Predicate<object> canExecute; 

    private event EventHandler CanExecuteChangedInternal; 

    public RelayCommand(Action<object> execute) 
     : this(execute, DefaultCanExecute) 
    { 
    } 

    public RelayCommand(Action<object> execute, Predicate<object> canExecute) 
    { 
     if (execute == null) 
     { 
      throw new ArgumentNullException("execute"); 
     } 

     if (canExecute == null) 
     { 
      throw new ArgumentNullException("canExecute"); 
     } 

     this.execute = execute; 
     this.canExecute = canExecute; 
    } 

    public event EventHandler CanExecuteChanged 
    { 
     add 
     { 
      CommandManager.RequerySuggested += value; 
      this.CanExecuteChangedInternal += value; 
     } 

     remove 
     { 
      CommandManager.RequerySuggested -= value; 
      this.CanExecuteChangedInternal -= value; 
     } 
    } 

    public bool CanExecute(object parameter) 
    { 
     return this.canExecute != null && this.canExecute(parameter); 
    } 

    public void Execute(object parameter) 
    { 
     this.execute(parameter); 
    } 

    public void OnCanExecuteChanged() 
    { 
     EventHandler handler = this.CanExecuteChangedInternal; 
     if (handler != null) 
     { 
      //DispatcherHelper.BeginInvokeOnUIThread(() => handler.Invoke(this, EventArgs.Empty)); 
      handler.Invoke(this, EventArgs.Empty); 
     } 
    } 

    public void Destroy() 
    { 
     this.canExecute = _ => false; 
     this.execute = _ => { return; }; 
    } 

    private static bool DefaultCanExecute(object parameter) 
    { 
     return true; 
    } 
} 

UPDATE:

我從DockPanel切換到StackPanel並設置寬度與StatusBox而不是允許LastChildFill的調整狀態字段和這解決了我的問題。儘管我在StatusBox的周圍放置了一個邊框以查看渲染的位置,但它仍然給我提出了問題。

+0

請解釋屬性'SaveEnabled'等或張貼更多的代碼。如果缺少一半的綁定,很難在綁定中發現錯誤。 – lhildebrandt

+0

@Ihildebrandt - 我爲您添加了SaveEnabled和ProgramEnabled屬性。 – Bluto

+0

是否帶有'SaveEnabled'的按鈕,導致麻煩?順便說一句,你的'ICommand'實現是怎樣的? – XAMlMAX

回答

0

根據是否可以執行該命令,您不需要明確地綁定到SaveEnabled屬性以使按鈕被取消/啓用。 只需在您的RelayCommand謂詞中包含您的CanExecute邏輯,並且如果屬性更改,請在您的命令中調用OnCanExecuteChanged以啓用該按鈕。

編輯

像這樣的事情

private ICommand saveCMD; 

public ICommand SaveCMD  
{ 
    get 
    { 
     if(this.saveCMD == null) 
     { 
     this.saveCMD = new RelayCommand(this.SaveSettings, this.CanSaveSettings) 
     } 

     return saveCMD; 
    } 
} 

public bool CanSaveSettings() 
{ 
    return ((tab1_Selected && tab1Data != null && tab1Data.Count > 0) || (tab2_Selected && tab2Data != null && tab2Data.Count > 0) && _saveEnabled); 
} 

然後在你看來,你應該能夠只使用這一點,它應該工作:

<Button Content="Save" x:Name="SaveBtn" Command="{Binding SaveCMD}" Padding="10,5" Margin= "10,0"/> 
+0

@Ihildebrandt,你可以舉個例子。我之前在其他項目中完成了此操作,無法使用戶界面刷新按鈕,而必須切換到調用Property Changed事件的屬性。因此,我爲什麼按照它的方式寫它。 – Bluto

+0

編輯我的主要帖子。請檢查是否解決了您的問題。 – lhildebrandt

+0

我試過了,並沒有幫助。程序啓動後,每隔一段時間我都不能單擊Read按鈕。 – Bluto