This commit is contained in:
yck1509 2014-06-22 22:11:17 +08:00
Родитель ff13dc386e
Коммит 8b92dc5a79
16 изменённых файлов: 429 добавлений и 37 удалений

Просмотреть файл

@ -64,6 +64,10 @@ namespace Confuser.Core {
context.token = token;
PrintInfo(context);
bool ok = false;
try {
var asmResolver = new AssemblyResolver();
asmResolver.EnableTypeDefCache = true;
asmResolver.DefaultModuleContext = new ModuleContext(asmResolver);
@ -73,10 +77,6 @@ namespace Confuser.Core {
foreach (string probePath in parameters.Project.ProbePaths)
asmResolver.PostSearchPaths.Add(Path.Combine(context.BaseDirectory, probePath));
PrintInfo(context);
bool ok = false;
try {
Marker marker = parameters.GetMarker();
// 2. Discover plugins
@ -94,8 +94,7 @@ namespace Confuser.Core {
try {
var resolver = new DependencyResolver(prots);
prots = resolver.SortDependency();
}
catch (CircularDependencyException ex) {
} catch (CircularDependencyException ex) {
context.Logger.ErrorException("", ex);
throw new ConfuserException(ex);
}
@ -122,8 +121,7 @@ namespace Confuser.Core {
foreach (ConfuserComponent comp in components) {
try {
comp.Initialize(context);
}
catch (Exception ex) {
} catch (Exception ex) {
context.Logger.ErrorException("Error occured during initialization of '" + comp.Name + "'.", ex);
throw new ConfuserException(ex);
}
@ -143,29 +141,21 @@ namespace Confuser.Core {
RunPipeline(pipeline, context);
ok = true;
}
catch (AssemblyResolveException ex) {
} catch (AssemblyResolveException ex) {
context.Logger.ErrorException("Failed to resolve a assembly, check if all dependencies are of correct version.", ex);
}
catch (TypeResolveException ex) {
} catch (TypeResolveException ex) {
context.Logger.ErrorException("Failed to resolve a type, check if all dependencies are of correct version.", ex);
}
catch (MemberRefResolveException ex) {
} catch (MemberRefResolveException ex) {
context.Logger.ErrorException("Failed to resolve a member, check if all dependencies are of correct version.", ex);
}
catch (IOException ex) {
} catch (IOException ex) {
context.Logger.ErrorException("An IO error occured, check if all input/output locations are read/writable.", ex);
}
catch (OperationCanceledException) {
} catch (OperationCanceledException) {
context.Logger.Error("Operation is canceled.");
}
catch (ConfuserException) {
} catch (ConfuserException) {
// Exception is already handled/logged, so just ignore and report failure
}
catch (Exception ex) {
} catch (Exception ex) {
context.Logger.ErrorException("Unknown error occured.", ex);
}
finally {
} finally {
context.Logger.Finish(ok);
}
}
@ -227,8 +217,7 @@ namespace Confuser.Core {
.SelectMany(module => module.GetAssemblyRefs().Select(asmRef => Tuple.Create(asmRef, module)))) {
try {
AssemblyDef assembly = context.Resolver.ResolveThrow(dependency.Item1, dependency.Item2);
}
catch (AssemblyResolveException ex) {
} catch (AssemblyResolveException ex) {
context.Logger.ErrorException("Failed to resolve dependency of '" + dependency.Item2.Name + "'.", ex);
throw new ConfuserException(ex);
}
@ -361,8 +350,7 @@ namespace Confuser.Core {
private static void PrintInfo(ConfuserContext context) {
if (context.PackerInitiated) {
context.Logger.Info("Protecting packer stub...");
}
else {
} else {
context.Logger.InfoFormat("{0} {1}", Version, Copyright);
Type mono = Type.GetType("Mono.Runtime");

Просмотреть файл

@ -0,0 +1,22 @@
using System;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Media;
namespace ConfuserEx {
public class BrushToColorConverter : IValueConverter {
public static readonly BrushToColorConverter Instance = new BrushToColorConverter();
private BrushToColorConverter() { }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
var brush = value as SolidColorBrush;
if (brush != null)
return brush.Color;
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
throw new NotImplementedException();
}
}
}

Просмотреть файл

@ -17,15 +17,19 @@ namespace ConfuserEx {
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
Debug.Assert(value is string);
Debug.Assert(value is string || value == null);
Debug.Assert(targetType == typeof (ConfuserComponent));
Debug.Assert(Components != null);
if (value == null) return null;
return Components.Single(comp => comp.Id == (string)value);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
Debug.Assert(value is ConfuserComponent);
Debug.Assert(value is ConfuserComponent || value == null);
Debug.Assert(targetType == typeof (string));
if (value == null) return null;
return ((ConfuserComponent)value).Id;
}

Просмотреть файл

@ -57,6 +57,10 @@
<HintPath>..\deps\Ookii.Dialogs.Wpf.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Threading, Version=1.0.2856.102, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\TaskParallelLibrary.1.0.2856.0\lib\Net35\System.Threading.dll</HintPath>
</Reference>
<Reference Include="System.Windows.Interactivity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\MvvmLightLibs.4.3.31.1\lib\net40\System.Windows.Interactivity.dll</HintPath>
</Reference>
@ -76,6 +80,7 @@
<Compile Include="..\GlobalAssemblyInfo.cs">
<Link>Properties\GlobalAssemblyInfo.cs</Link>
</Compile>
<Compile Include="BrushToColorConverter.cs" />
<Compile Include="CompComboBox.xaml.cs">
<DependentUpon>CompComboBox.xaml</DependentUpon>
</Compile>
@ -83,6 +88,7 @@
<Compile Include="ComponentDiscovery.cs" />
<Compile Include="EnumValuesExtension.cs" />
<Compile Include="FileDragDrop.cs" />
<Compile Include="InvertBoolConverter.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Skin.cs" />
<Compile Include="ViewModel\Project\ProjectRuleVM.cs" />
@ -93,6 +99,7 @@
<Compile Include="ViewModel\Project\ProjectModuleVM.cs" />
<Compile Include="ViewModel\UI\ProjectTabVM.cs" />
<Compile Include="ViewModel\Project\ProjectVM.cs" />
<Compile Include="ViewModel\UI\ProtectTabVM.cs" />
<Compile Include="ViewModel\UI\SettingsTabVM.cs" />
<Compile Include="ViewModel\UI\TabViewModel.cs" />
<Compile Include="ViewModel\Utils.cs" />
@ -130,6 +137,10 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\ProtectTabView.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\ProjectRuleView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>

Просмотреть файл

@ -0,0 +1,21 @@
using System;
using System.Diagnostics;
using System.Globalization;
using System.Windows.Data;
namespace ConfuserEx {
internal class InvertBoolConverter : IValueConverter {
public static readonly InvertBoolConverter Instance = new InvertBoolConverter();
private InvertBoolConverter() { }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
Debug.Assert(value is bool);
Debug.Assert(targetType == typeof (bool));
return !(bool)value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
throw new NotSupportedException();
}
}
}

Просмотреть файл

@ -1,6 +1,7 @@
<Window x:Class="ConfuserEx.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ConfuserEx"
Title="{Binding Title}" Width="800" Height="600" Style="{StaticResource DarkWindow}">
<Grid>
<Grid.RowDefinitions>
@ -47,7 +48,7 @@
</Button>
</ToolBar>
<TabControl Grid.Row="1" Grid.ColumnSpan="2" Margin="10" ItemsSource="{Binding Tabs}" Padding="5"
SelectedIndex="0">
SelectedIndex="0" local:Skin.TabsDisabled="{Binding NavigationDisabled}">
<TabControl.ItemContainerStyle>
<Style TargetType="{x:Type TabItem}" BasedOn="{StaticResource {x:Type TabItem}}">
<Setter Property="Width" Value="80" />

Просмотреть файл

@ -17,6 +17,7 @@ namespace ConfuserEx {
app.Tabs.Add(new ProjectTabVM(app));
app.Tabs.Add(new SettingsTabVM(app));
app.Tabs.Add(new ProtectTabVM(app));
DataContext = app;
}

Просмотреть файл

@ -1,11 +1,19 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
namespace ConfuserEx {
public class Skin {
public static readonly DependencyProperty EmptyPromptProperty =
DependencyProperty.RegisterAttached("EmptyPrompt", typeof (string), typeof (Skin), new UIPropertyMetadata(null));
public static readonly DependencyProperty TabsDisabledProperty =
DependencyProperty.RegisterAttached("TabsDisabled", typeof (bool), typeof (Skin), new UIPropertyMetadata(false));
public static readonly DependencyProperty RTBDocumentProperty =
DependencyProperty.RegisterAttached("RTBDocument", typeof (FlowDocument), typeof (Skin), new FrameworkPropertyMetadata(null, OnRTBDocumentChanged));
public static string GetEmptyPrompt(DependencyObject obj) {
return (string)obj.GetValue(EmptyPromptProperty);
}
@ -13,5 +21,27 @@ namespace ConfuserEx {
public static void SetEmptyPrompt(DependencyObject obj, string value) {
obj.SetValue(EmptyPromptProperty, value);
}
public static bool GetTabsDisabled(DependencyObject obj) {
return (bool)obj.GetValue(TabsDisabledProperty);
}
public static void SetTabsDisabled(DependencyObject obj, bool value) {
obj.SetValue(TabsDisabledProperty, value);
}
public static void OnRTBDocumentChanged(DependencyObject d, DependencyPropertyChangedEventArgs dpe) {
var rtb = (RichTextBox)d;
rtb.Document = (FlowDocument)dpe.NewValue;
rtb.TextChanged += (sender, e) => rtb.ScrollToEnd();
}
public static FlowDocument GetRTBDocument(DependencyObject obj) {
return (FlowDocument)obj.GetValue(RTBDocumentProperty);
}
public static void SetRTBDocument(DependencyObject obj, FlowDocument value) {
obj.SetValue(RTBDocumentProperty, value);
}
}
}

Просмотреть файл

@ -358,7 +358,8 @@
<RowDefinition x:Name="RowDefinition1" Height="*" />
</Grid.RowDefinitions>
<TabPanel x:Name="HeaderPanel" Background="Transparent" Grid.Column="0" IsItemsHost="true"
Margin="0,2,2,-1" Grid.Row="0" KeyboardNavigation.TabIndex="1" Panel.ZIndex="1" />
Margin="0,2,2,-1" Grid.Row="0" KeyboardNavigation.TabIndex="1" Panel.ZIndex="1"
IsEnabled="{Binding Path=(local:Skin.TabsDisabled), RelativeSource={RelativeSource TemplatedParent}, Converter={x:Static local:InvertBoolConverter.Instance}}" />
<Grid x:Name="ContentPanel" Grid.Column="0"
KeyboardNavigation.DirectionalNavigation="Contained" Grid.Row="1"
KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local">
@ -702,6 +703,58 @@
</Setter>
</Style>
<Style TargetType="{x:Type RichTextBox}">
<Setter Property="BorderBrush" Value="{StaticResource Border}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Foreground" Value="{StaticResource Foreground}" />
<Setter Property="Background" Value="{StaticResource ControlBackground}" />
<Setter Property="Padding" Value="1" />
<Setter Property="KeyboardNavigation.TabNavigation" Value="None" />
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="AllowDrop" Value="true" />
<Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst" />
<Setter Property="Stylus.IsFlicksEnabled" Value="False" />
<Setter Property="SelectionBrush" Value="{StaticResource Foreground}" />
<Setter Property="SelectionOpacity" Value="0.2" />
<Setter Property="CaretBrush" Value="{StaticResource Border}" />
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu>
<MenuItem Header="Undo" Command="ApplicationCommands.Undo" />
<MenuItem Header="Redo" Command="ApplicationCommands.Redo" />
<Separator />
<MenuItem Header="Cut" Command="ApplicationCommands.Cut" />
<MenuItem Header="Copy" Command="ApplicationCommands.Copy" />
<MenuItem Header="Paste" Command="ApplicationCommands.Paste" />
</ContextMenu>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RichTextBox}">
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}">
<Grid>
<Border x:Name="Overlay" Background="{StaticResource HighlightOverlay}" Opacity="0" />
<ScrollViewer x:Name="PART_ContentHost" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="Bd" Value="{StaticResource DisabledBackground}" />
<Setter Property="Foreground" Value="{StaticResource DisabledForeground}" />
</Trigger>
<Trigger Property="IsFocused" Value="true">
<Setter Property="Opacity" TargetName="Overlay" Value="0.5" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="CheckRadioFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
@ -1359,4 +1412,90 @@
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type ProgressBar}">
<Setter Property="Background" Value="{StaticResource ControlBackground}" />
<Setter Property="Foreground" Value="{StaticResource Foreground}" />
<Setter Property="BorderBrush" Value="{StaticResource Border}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ProgressBar}">
<Grid MinHeight="14" MinWidth="200" Background="{TemplateBinding Background}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Determinate" />
<VisualState x:Name="Indeterminate">
<Storyboard>
<ObjectAnimationUsingKeyFrames Duration="0"
Storyboard.TargetName="PART_Indicator"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<SolidColorBrush Color="Transparent" />
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Duration="0"
Storyboard.TargetName="Animation"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation
Storyboard.TargetName="animTranslate"
Storyboard.TargetProperty="X"
From="0" To="50" Duration="0:0:1" RepeatBehavior="Forever" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="PART_Track"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}" />
<Border x:Name="PART_Indicator"
HorizontalAlignment="Left"
Background="{TemplateBinding Foreground}"
Margin="3">
<Border x:Name="Animation" Visibility="Hidden">
<Border.Background>
<DrawingBrush TileMode="Tile" Viewport="0,0,25,25" ViewportUnits="Absolute">
<DrawingBrush.Transform>
<TranslateTransform x:Name="animTranslate" />
</DrawingBrush.Transform>
<DrawingBrush.Drawing>
<GeometryDrawing>
<GeometryDrawing.Brush>
<LinearGradientBrush SpreadMethod="Repeat" StartPoint="0,0"
EndPoint="1,1">
<LinearGradientBrush.RelativeTransform>
<ScaleTransform ScaleX="0.5" ScaleY="0.5" />
</LinearGradientBrush.RelativeTransform>
<GradientStop Offset="0" Color="Transparent" />
<GradientStop Offset="0.5" Color="Transparent" />
<GradientStop Offset="0.5"
Color="{Binding Foreground, Converter={x:Static local:BrushToColorConverter.Instance}, RelativeSource={RelativeSource Mode=TemplatedParent}}" />
<GradientStop Offset="1"
Color="{Binding Foreground, Converter={x:Static local:BrushToColorConverter.Instance}, RelativeSource={RelativeSource Mode=TemplatedParent}}" />
</LinearGradientBrush>
</GeometryDrawing.Brush>
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,0,10,10" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</Border.Background>
</Border>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

Просмотреть файл

@ -19,6 +19,9 @@ namespace ConfuserEx.ViewModel {
ObservableCollection<ProjectRuleVM> rules = Utils.Wrap(module.Rules, rule => new ProjectRuleVM(parent, rule));
rules.CollectionChanged += (sender, e) => parent.IsModified = true;
Rules = rules;
SimpleName = System.IO.Path.GetFileName(module.Path);
LoadAssemblyName();
}
public ProjectModule Module {

Просмотреть файл

@ -23,6 +23,8 @@ namespace ConfuserEx.ViewModel {
ObservableCollection<ProjectSettingVM<Protection>> protections = Utils.Wrap(rule, setting => new ProjectSettingVM<Protection>(parent, setting));
protections.CollectionChanged += (sender, e) => parent.IsModified = true;
Protections = protections;
ParseExpression();
}
public ProjectVM Project {

Просмотреть файл

@ -0,0 +1,131 @@
using System;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using Confuser.Core;
using Confuser.Core.Project;
using GalaSoft.MvvmLight.Command;
namespace ConfuserEx.ViewModel {
internal class ProtectTabVM : TabViewModel, ILogger {
private readonly Paragraph documentContent;
private double? progress = 0;
private bool? result;
public ProtectTabVM(AppVM app)
: base(app, "Protect!") {
documentContent = new Paragraph();
LogDocument = new FlowDocument();
LogDocument.Blocks.Add(documentContent);
}
public ICommand ProtectCmd {
get { return new RelayCommand(DoProtect, () => !App.NavigationDisabled); }
}
public double? Progress {
get { return progress; }
set { SetProperty(ref progress, value, "Progress"); }
}
public FlowDocument LogDocument { get; private set; }
public bool? Result {
get { return result; }
set { SetProperty(ref result, value, "Result"); }
}
private void DoProtect() {
var parameters = new ConfuserParameters();
parameters.Project = ((IViewModel<ConfuserProject>)App.Project).Model;
parameters.Logger = this;
documentContent.Inlines.Clear();
App.NavigationDisabled = true;
Result = null;
begin = DateTime.Now;
ConfuserEngine.Run(parameters)
.ContinueWith(_ =>
Application.Current.Dispatcher.BeginInvoke(new Action(() => {
Progress = 0;
App.NavigationDisabled = false;
CommandManager.InvalidateRequerySuggested();
})));
}
private void AppendLine(string format, Brush foreground, params object[] args) {
Application.Current.Dispatcher.BeginInvoke(new Action(() => {
documentContent.Inlines.Add(new Run(string.Format(format, args)) { Foreground = foreground });
documentContent.Inlines.Add(new LineBreak());
}));
}
#region Logger Impl
private DateTime begin;
public void Debug(string msg) {
AppendLine("[DEBUG] {0}", Brushes.Gray, msg);
}
public void DebugFormat(string format, params object[] args) {
AppendLine("[DEBUG] {0}", Brushes.Gray, string.Format(format, args));
}
public void Info(string msg) {
AppendLine(" [INFO] {0}", Brushes.White, msg);
}
public void InfoFormat(string format, params object[] args) {
AppendLine(" [INFO] {0}", Brushes.White, string.Format(format, args));
}
public void Warn(string msg) {
AppendLine(" [WARN] {0}", Brushes.Yellow, msg);
}
public void WarnFormat(string format, params object[] args) {
AppendLine(" [WARN] {0}", Brushes.Yellow, string.Format(format, args));
}
public void WarnException(string msg, Exception ex) {
AppendLine(" [WARN] {0}", Brushes.Yellow, msg);
AppendLine("Exception: {0}", Brushes.Yellow, ex);
}
public void Error(string msg) {
AppendLine("[ERROR] {0}", Brushes.Red, msg);
}
public void ErrorFormat(string format, params object[] args) {
AppendLine("[ERROR] {0}", Brushes.Red, string.Format(format, args));
}
public void ErrorException(string msg, Exception ex) {
AppendLine("[ERROR] {0}", Brushes.Red, msg);
AppendLine("Exception: {0}", Brushes.Red, ex);
}
void ILogger.Progress(int overall, int progress) {
Progress = (double)progress / overall;
}
public void Finish(bool successful) {
DateTime now = DateTime.Now;
string timeString = string.Format(
"at {0}, {1}:{2:d2} elapsed.",
now.ToShortTimeString(),
(int)now.Subtract(begin).TotalMinutes,
now.Subtract(begin).Seconds);
if (successful)
AppendLine("Finished {0}", Brushes.Lime, timeString);
else
AppendLine("Failed {0}", Brushes.Red, timeString);
Result = successful;
}
#endregion
}
}

Просмотреть файл

@ -88,6 +88,8 @@ namespace ConfuserEx.ViewModel {
App.Project,
new CollectionContainer { Collection = App.Project.Modules }
};
OnPropertyChanged("ModulesView");
HasPacker = App.Project.Packer != null;
}
protected override void OnPropertyChanged(string property) {

Просмотреть файл

@ -3,5 +3,6 @@
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Views\ProjectTabView.xaml" />
<ResourceDictionary Source="Views\SettingsTabView.xaml" />
<ResourceDictionary Source="Views\ProtectTabView.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

Просмотреть файл

@ -0,0 +1,35 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ConfuserEx"
xmlns:vm="clr-namespace:ConfuserEx.ViewModel">
<DataTemplate DataType="{x:Type vm:ProtectTabVM}">
<Grid Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="40px" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="100px" />
</Grid.ColumnDefinitions>
<ProgressBar x:Name="progress" Grid.Row="0" Grid.Column="0" Margin="5"
Value="{Binding Progress}" Minimum="0" Maximum="1" />
<Button Grid.Row="0" Grid.Column="1" Margin="5" Content="Protect!" Command="{Binding ProtectCmd}" />
<RichTextBox x:Name="log" Grid.Row="1" Grid.ColumnSpan="2" Margin="5" FontFamily="Consolas"
IsReadOnly="True" IsReadOnlyCaretVisible="True" local:Skin.RTBDocument="{Binding LogDocument}"
VerticalScrollBarVisibility="Visible" />
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Progress}" Value="{x:Null}">
<Setter TargetName="progress" Property="IsIndeterminate" Value="True" />
</DataTrigger>
<DataTrigger Binding="{Binding Result}" Value="True">
<Setter TargetName="log" Property="BorderBrush" Value="#40ff40" />
</DataTrigger>
<DataTrigger Binding="{Binding Result}" Value="False">
<Setter TargetName="log" Property="BorderBrush" Value="#ff4040" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ResourceDictionary>

Просмотреть файл

@ -3,4 +3,5 @@
<packages>
<package id="CommonServiceLocator" version="1.2" targetFramework="net40" />
<package id="MvvmLightLibs" version="4.3.31.1" targetFramework="net40" />
<package id="TaskParallelLibrary" version="1.0.2856.0" targetFramework="net40" />
</packages>