【发布时间】:2016-10-05 16:02:02
【问题描述】:
我有一个 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;
}
}
更新:
我从DockPanel 切换到StackPanel 并将宽度设置为StatusBox,而不是允许LastChildFill 调整状态字段,这解决了我的问题。即使我在 StatusBox 周围设置了一个边框以查看它的渲染位置,它仍然给我带来了问题。
【问题讨论】:
-
请解释
SaveEnabled等的属性或发布更多代码。如果缺少一半,很难在绑定中找到错误。 -
@Ihildebrandt - 我已经为你添加了 SaveEnabled 和 ProgramEnabled 属性。
-
是不是有
SaveEnabled的按钮有问题?顺便说一句,您的ICommand实现如何? -
我添加了 ICommand 信息。是“阅读”按钮给了我这个问题。程序首次启动时,保存按钮被禁用。