我使用WIX bootstrapper UI编写了一个安装程序。当我运行安装程序时,只启用了取消按钮状态,但其他状态已正确配置。下面是我的模特课。
public class BootstrapperApplicationModel
{
private IntPtr hwnd;
public BootstrapperApplicationModel(
BootstrapperApplication bootstrapperApplication)
{
this.BootstrapperApplication = bootstrapperApplication;
this.hwnd = IntPtr.Zero;
}
public BootstrapperApplication BootstrapperApplication
{
get;
private set;
}
public int FinalResult { get; set; }
public void SetWindowHandle(Window view)
{
this.hwnd = new WindowInteropHelper(view).Handle;
}
public void PlanAction(LaunchAction action)
{
this.BootstrapperApplication.Engine.Plan(action);
}
public void ApplyAction()
{
this.BootstrapperApplication.Engine.Apply(this.hwnd);
}
public void LogMessage(string message)
{
this.BootstrapperApplication.Engine.Log(LogLevel.Standard,message);
}
}
以下是我的观点模型
public class InstallViewModel : BindableBase
{
public enum InstallState
{
Initializing,
Present,
NotPresent,
Applying,
Cancelled
}
private InstallState state;
private string message;
private BootstrapperApplicationModel model;
public ICommand InstallCommand { get; private set; }
public ICommand UninstallCommand { get; private set; }
public ICommand CancelCommand { get; private set; }
public string Message
{
get
{
return this.message;
}
set
{
if (this.message != value)
{
this.message = value;
this.OnPropertyChanged(() => this.Message);
}
}
}
public InstallState State
{
get
{
return this.state;
}
set
{
if (this.state != value)
{
this.state = value;
this.Message = this.state.ToString();
this.OnPropertyChanged(() => this.State);
this.Refresh();
}
}
}
public InstallViewModel(
BootstrapperApplicationModel model)
{
this.model = model;
this.State = InstallState.Initializing;
this.WireUpEventHandlers();
this.InstallCommand = new DelegateCommand(() =>
this.model.PlanAction(LaunchAction.Install),
() => this.State == InstallState.NotPresent);
this.UninstallCommand = new DelegateCommand(() =>
this.model.PlanAction(LaunchAction.Uninstall),
() => this.State == InstallState.Present);
this.CancelCommand = new DelegateCommand(() =>
{
this.model.LogMessage("Cancelling...");
if (this.State == InstallState.Applying)
{
this.State = InstallState.Cancelled;
}
else
{
CustomBootstrapperApplication.Dispatcher
.InvokeShutdown();
}
}, () => this.State != InstallState.Cancelled);
}
protected void DetectPackageComplete(
object sender,
DetectPackageCompleteEventArgs e)
{
if (e.PackageId.Equals(
"MyInstaller.msi", StringComparison.Ordinal))
{
this.State = e.State == PackageState.Present ?
InstallState.Present : InstallState.NotPresent;
}
}
protected void PlanComplete(
object sender, PlanCompleteEventArgs e)
{
if (this.State == InstallState.Cancelled)
{
CustomBootstrapperApplication.Dispatcher
.InvokeShutdown();
return;
}
this.model.ApplyAction();
}
protected void ApplyBegin(
object sender, ApplyBeginEventArgs e)
{
this.State = InstallState.Applying;
}
protected void ExecutePackageBegin(
object sender, ExecutePackageBeginEventArgs e)
{
if (this.State == InstallState.Cancelled)
{
e.Result = Result.Cancel;
}
}
protected void ExecutePackageComplete(
object sender, ExecutePackageCompleteEventArgs e)
{
if (this.State == InstallState.Cancelled)
{
e.Result = Result.Cancel;
}
}
protected void ApplyComplete(
object sender, ApplyCompleteEventArgs e)
{
this.model.FinalResult = e.Status;
CustomBootstrapperApplication.Dispatcher
.InvokeShutdown();
}
private void Refresh()
{
CustomBootstrapperApplication.Dispatcher.Invoke(
(Action)(() =>
{
((DelegateCommand)this.InstallCommand)
.RaiseCanExecuteChanged();
((DelegateCommand)this.UninstallCommand)
.RaiseCanExecuteChanged();
((DelegateCommand)this.CancelCommand)
.RaiseCanExecuteChanged();
}));
}
private void WireUpEventHandlers()
{
this.model.BootstrapperApplication.DetectPackageComplete
+= this.DetectPackageComplete;
this.model.BootstrapperApplication.PlanComplete += this.
PlanComplete;
this.model.BootstrapperApplication.ApplyComplete += this.
ApplyComplete;
this.model.BootstrapperApplication.ApplyBegin += this.
ApplyBegin;
this.model.BootstrapperApplication.ExecutePackageBegin +=
this.ExecutePackageBegin;
this.model.BootstrapperApplication.ExecutePackageComplete
+= this.ExecutePackageComplete;
}
}
以下是我对XAML及其后端代码的看法。
<Window x:Class="CustomBA.Views.InstallView"
xmlns=
"http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc=
"http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d=
"http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Window.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Margin" Value="10" />
<Setter Property="Height" Value="30" />
</Style>
</Window.Resources>
<Grid>
<StackPanel>
<Label Content="{Binding Message}" />
<Button Command="{Binding InstallCommand}">
Install</Button>
<Button Command="{Binding UninstallCommand}">
Uninstall</Button>
<Button Command="{Binding CancelCommand}">
Cancel</Button>
</StackPanel>
</Grid>
</Window>
public partial class InstallView : Window
{
public InstallView(InstallViewModel viewModel)
{
this.InitializeComponent();
this.DataContext = viewModel;
this.Closed += (sender, e) =>
viewModel.CancelCommand.Execute(this);
}
}
我在这里做错了什么?请指教。
以下是我运行时的样子。
答案 0 :(得分:1)
您似乎遇到了WPF没有重新评估命令条件的问题。 This answer很好地涵盖了您的选择 - 尝试CommandManager.InvalidateRequerySuggested();
或在命令中提升CanExecuteChanged
事件。