Skip to content

Commit d968d35

Browse files
committed
Merge remote-tracking branch 'origin/pr/350' into winforms
2 parents 479ed66 + e902357 commit d968d35

16 files changed

+1452
-23
lines changed
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup>
4+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6+
<ProductVersion>8.0.30703</ProductVersion>
7+
<SchemaVersion>2.0</SchemaVersion>
8+
<ProjectGuid>{F5ECBDE5-E525-4482-B568-63217BCB0A0B}</ProjectGuid>
9+
<OutputType>Library</OutputType>
10+
<AppDesignerFolder>Properties</AppDesignerFolder>
11+
<RootNamespace>ReactiveUI</RootNamespace>
12+
<AssemblyName>ReactiveUI.Winforms</AssemblyName>
13+
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
14+
<FileAlignment>512</FileAlignment>
15+
<SccProjectName>
16+
</SccProjectName>
17+
<SccLocalPath>
18+
</SccLocalPath>
19+
<SccAuxPath>
20+
</SccAuxPath>
21+
<SccProvider>
22+
</SccProvider>
23+
<CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
24+
<Utf8Output>true</Utf8Output>
25+
<ExpressionBlendVersion>4.0.30816.0</ExpressionBlendVersion>
26+
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
27+
<RestorePackages>true</RestorePackages>
28+
</PropertyGroup>
29+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
30+
<DebugSymbols>true</DebugSymbols>
31+
<DebugType>full</DebugType>
32+
<Optimize>false</Optimize>
33+
<OutputPath>bin\Debug\Net45\</OutputPath>
34+
<DefineConstants>DEBUG;TRACE;NET_45</DefineConstants>
35+
<ErrorReport>prompt</ErrorReport>
36+
<WarningLevel>4</WarningLevel>
37+
<CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
38+
<CodeContractsRuntimeOnlyPublicSurface>True</CodeContractsRuntimeOnlyPublicSurface>
39+
<CodeContractsRuntimeThrowOnFailure>False</CodeContractsRuntimeThrowOnFailure>
40+
<CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
41+
<CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
42+
<CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
43+
<CodeContractsBoundsObligations>True</CodeContractsBoundsObligations>
44+
<CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
45+
<CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
46+
<CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
47+
<CodeContractsRunInBackground>True</CodeContractsRunInBackground>
48+
<CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
49+
<CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
50+
<CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
51+
<CodeContractsCustomRewriterAssembly />
52+
<CodeContractsCustomRewriterClass />
53+
<CodeContractsLibPaths />
54+
<CodeContractsExtraRewriteOptions />
55+
<CodeContractsExtraAnalysisOptions />
56+
<CodeContractsBaseLineFile />
57+
<CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
58+
<CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
59+
<CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
60+
<CodeAnalysisRuleSet>ExtendedCorrectnessRules.ruleset</CodeAnalysisRuleSet>
61+
<RunCodeAnalysis>false</RunCodeAnalysis>
62+
<CodeContractsPointerObligations>False</CodeContractsPointerObligations>
63+
</PropertyGroup>
64+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
65+
<DebugType>pdbonly</DebugType>
66+
<Optimize>true</Optimize>
67+
<OutputPath>bin\Release\Net45\</OutputPath>
68+
<DefineConstants>TRACE;NET_45</DefineConstants>
69+
<ErrorReport>prompt</ErrorReport>
70+
<WarningLevel>4</WarningLevel>
71+
<CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
72+
<CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
73+
<CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
74+
<CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
75+
<CodeContractsRunCodeAnalysis>True</CodeContractsRunCodeAnalysis>
76+
<CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
77+
<CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
78+
<CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
79+
<CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
80+
<CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
81+
<CodeContractsRunInBackground>True</CodeContractsRunInBackground>
82+
<CodeContractsShowSquigglies>True</CodeContractsShowSquigglies>
83+
<CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
84+
<CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
85+
<CodeContractsCustomRewriterAssembly />
86+
<CodeContractsCustomRewriterClass />
87+
<CodeContractsLibPaths />
88+
<CodeContractsExtraRewriteOptions />
89+
<CodeContractsExtraAnalysisOptions />
90+
<CodeContractsBaseLineFile />
91+
<CodeContractsCacheAnalysisResults>True</CodeContractsCacheAnalysisResults>
92+
<CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
93+
<CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
94+
<DocumentationFile>bin\Release\Net45\ReactiveUI.Winforms.xml</DocumentationFile>
95+
<NoWarn>1591, 1573, 1711, 1587, 1570, 1572</NoWarn>
96+
</PropertyGroup>
97+
<ItemGroup>
98+
<Reference Include="System" />
99+
<Reference Include="System.ComponentModel.DataAnnotations" />
100+
<Reference Include="System.Core" />
101+
<Reference Include="System.Reactive.Core">
102+
<HintPath>..\ext\Portable-Net45+WinRT45+WP8\System.Reactive.Core.dll</HintPath>
103+
</Reference>
104+
<Reference Include="System.Reactive.Interfaces">
105+
<HintPath>..\ext\Portable-Net45+WinRT45+WP8\System.Reactive.Interfaces.dll</HintPath>
106+
</Reference>
107+
<Reference Include="System.Reactive.Linq">
108+
<HintPath>..\ext\Portable-Net45+WinRT45+WP8\System.Reactive.Linq.dll</HintPath>
109+
</Reference>
110+
<Reference Include="System.Reactive.PlatformServices">
111+
<HintPath>..\ext\net45\System.Reactive.PlatformServices.dll</HintPath>
112+
</Reference>
113+
<Reference Include="System.Reactive.Windows.Threading, Version=2.0.20823.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
114+
<SpecificVersion>False</SpecificVersion>
115+
<HintPath>..\ext\net45\System.Reactive.Windows.Threading.dll</HintPath>
116+
</Reference>
117+
<Reference Include="System.Runtime.Serialization" />
118+
<Reference Include="System.Windows.Forms" />
119+
<Reference Include="System.Xaml" />
120+
<Reference Include="System.Xml.Linq" />
121+
<Reference Include="Microsoft.CSharp" />
122+
<Reference Include="System.Xml" />
123+
</ItemGroup>
124+
<ItemGroup>
125+
<Compile Include="ComponentModelTypeConverter.cs" />
126+
<Compile Include="Winforms\ReactiveBindingList.cs" />
127+
<Compile Include="Winforms\CreatesCommandBinding.cs" />
128+
<Compile Include="Winforms\PlatformOperations.cs" />
129+
<Compile Include="Winforms\PlatformUnitTestDetector.cs" />
130+
<Compile Include="Winforms\Properties\AssemblyInfo.cs" />
131+
<Compile Include="Winforms\Registrations.cs" />
132+
<Compile Include="Winforms\WinformsDefaultPropertyBinding.cs" />
133+
</ItemGroup>
134+
<ItemGroup>
135+
<ProjectReference Include="..\ReactiveUI\ReactiveUI.csproj">
136+
<Project>{464cb812-f99f-401b-be4c-e8f0515cd19d}</Project>
137+
<Name>ReactiveUI</Name>
138+
</ProjectReference>
139+
</ItemGroup>
140+
<ItemGroup>
141+
<Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
142+
<None Include="packages.config">
143+
<SubType>Designer</SubType>
144+
</None>
145+
</ItemGroup>
146+
<ItemGroup>
147+
<Folder Include="Properties\" />
148+
</ItemGroup>
149+
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
150+
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
151+
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
152+
Other similar extension points exist, see Microsoft.Common.targets.
153+
<Target Name="BeforeBuild">
154+
</Target>
155+
<Target Name="AfterBuild">
156+
</Target>
157+
-->
158+
</Project>
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Reactive.Disposables;
5+
using System.Reactive.Linq;
6+
using System.Windows.Forms;
7+
using System.Windows.Input;
8+
using ReactiveUI;
9+
10+
namespace ReactiveUI.Winforms
11+
{
12+
13+
14+
/// <summary>
15+
/// This binder is the default binder for connecting to arbitrary events
16+
/// </summary>
17+
public class CreatesWinformsCommandBinding : ICreatesCommandBinding
18+
{
19+
// NB: These are in priority order
20+
static readonly List<Tuple<string, Type>> defaultEventsToBind = new List<Tuple<string, Type>>() {
21+
22+
Tuple.Create("Click", typeof (EventArgs)),
23+
Tuple.Create("MouseUp", typeof (MouseEventArgs)),
24+
};
25+
26+
public int GetAffinityForObject(Type type, bool hasEventTarget)
27+
{
28+
bool isWinformControl = typeof(Control).IsAssignableFrom(type);
29+
30+
if (isWinformControl) return 10;
31+
32+
if (hasEventTarget) return 5;
33+
34+
return defaultEventsToBind.Any(x =>{
35+
var ei = type.GetEvent(x.Item1, BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.Instance);
36+
return ei != null;
37+
}) ? 3 : 0;
38+
}
39+
40+
public IDisposable BindCommandToObject(ICommand command, object target, IObservable<object> commandParameter)
41+
{
42+
const BindingFlags bf = BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy;
43+
44+
var type = target.GetType();
45+
var eventInfo = defaultEventsToBind
46+
.Select(x => new { EventInfo = type.GetEvent(x.Item1, bf), Args = x.Item2 })
47+
.FirstOrDefault(x => x.EventInfo != null);
48+
49+
if (eventInfo == null) return null;
50+
51+
var mi = this.GetType().GetMethods().First(x => x.Name == "BindCommandToObject" && x.IsGenericMethod);
52+
mi = mi.MakeGenericMethod(eventInfo.Args);
53+
54+
return (IDisposable)mi.Invoke(this, new[] { command, target, commandParameter, eventInfo.EventInfo.Name });
55+
}
56+
57+
public IDisposable BindCommandToObject<TEventArgs>(ICommand command, object target, IObservable<object> commandParameter, string eventName)
58+
{
59+
var ret = new CompositeDisposable();
60+
61+
object latestParameter = null;
62+
bool useEventArgsInstead = false;
63+
64+
// NB: This is a bit of a hack - if commandParameter isn't specified,
65+
// it will default to Observable.Empty. We're going to use termination
66+
// of the commandParameter as a signal to use EventArgs.
67+
ret.Add(commandParameter.Subscribe(
68+
x => latestParameter = x,
69+
() => useEventArgsInstead = true));
70+
71+
var evt = Observable.FromEventPattern<TEventArgs>(target, eventName);
72+
ret.Add(evt.Subscribe(ea =>
73+
{
74+
if (command.CanExecute(useEventArgsInstead ? ea : latestParameter)){
75+
command.Execute(useEventArgsInstead ? ea : latestParameter);
76+
}
77+
}));
78+
79+
return ret;
80+
}
81+
}
82+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace ReactiveUI.Winforms
8+
{
9+
public class PlatformOperations : IPlatformOperations
10+
{
11+
public string GetOrientation()
12+
{
13+
return null;
14+
}
15+
}
16+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+

2+
#if SILVERLIGHT
3+
using System.Windows;
4+
#elif WINRT
5+
using Windows.ApplicationModel;
6+
#endif
7+
8+
namespace ReactiveUI.Winforms
9+
{
10+
using System;
11+
using System.IO;
12+
using System.Reflection;
13+
using System.Linq;
14+
15+
/// <summary>
16+
/// Because RxUI.dll is in a PLib, it doesn't have the SuperPowers it needs
17+
/// to be able to really detect whether it's in a unit test runner. This class
18+
/// is much better at it.
19+
/// </summary>
20+
static class PlatformUnitTestDetector
21+
{
22+
public static bool InUnitTestRunner(string[] testAssemblies, string[] designEnvironments)
23+
{
24+
if (DesignModeDetector.IsInDesignMode()) return true;
25+
26+
#if SILVERLIGHT
27+
// NB: Deployment.Current.Parts throws an exception when accessed in Blend
28+
try {
29+
var ret = Deployment.Current.Parts.Any(x =>
30+
testAssemblies.Any(name => x.Source.ToUpperInvariant().Contains(name)));
31+
32+
if (ret) {
33+
return ret;
34+
}
35+
} catch(Exception) {
36+
return true;
37+
}
38+
39+
try {
40+
if (Application.Current.RootVisual != null && System.ComponentModel.DesignerProperties.GetIsInDesignMode(Application.Current.RootVisual)) {
41+
return false;
42+
}
43+
} catch {
44+
return true;
45+
}
46+
47+
return false;
48+
#elif WINRT
49+
if (DesignMode.DesignModeEnabled) return true;
50+
51+
var depPackages = Package.Current.Dependencies.Select(x => x.Id.FullName);
52+
if (depPackages.Any(x => testAssemblies.Any(name => x.ToUpperInvariant().Contains(name)))) return true;
53+
54+
55+
var fileTask = Task.Factory.StartNew(async () => {
56+
var files = await Package.Current.InstalledLocation.GetFilesAsync();
57+
return files.Select(x => x.Path).ToArray();
58+
}, TaskCreationOptions.HideScheduler).Unwrap();
59+
60+
return fileTask.Result.Any(x => testAssemblies.Any(name => x.ToUpperInvariant().Contains(name)));
61+
#else
62+
// Try to detect whether we're in design mode - bonus points,
63+
// without access to any WPF references :-/
64+
var entry = Assembly.GetEntryAssembly();
65+
if (entry != null) {
66+
var exeName = (new FileInfo(entry.Location)).Name.ToUpperInvariant();
67+
68+
if (designEnvironments.Any(x => x.Contains(exeName))) {
69+
return true;
70+
}
71+
}
72+
73+
return AppDomain.CurrentDomain.GetAssemblies().Any(x =>
74+
testAssemblies.Any(name => x.FullName.ToUpperInvariant().Contains(name)));
75+
#endif
76+
}
77+
78+
public static bool InUnitTestRunner()
79+
{
80+
// XXX: This is hacky and evil, but I can't think of any better way
81+
// to do this
82+
string[] testAssemblies = new[] {
83+
"CSUNIT",
84+
"NUNIT",
85+
"XUNIT",
86+
"MBUNIT",
87+
"PEX.",
88+
"NBEHAVE",
89+
};
90+
91+
string[] designEnvironments = new[] {
92+
"BLEND.EXE",
93+
"XDESPROC.EXE",
94+
};
95+
96+
return InUnitTestRunner(testAssemblies, designEnvironments);
97+
}
98+
}
99+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using System.Reflection;
2+
using System.Runtime.InteropServices;
3+
using System.Runtime.CompilerServices;
4+
using System.Windows;
5+
6+
[assembly: AssemblyDescription("An MVVM framework that integrates the Reactive Extensions")]
7+
[assembly: AssemblyProduct("ReactiveUI.Winforms")]
8+
[assembly: AssemblyVersion("5.0.1")]
9+
[assembly: InternalsVisibleTo("ReactiveUI.Tests_Net45")]

0 commit comments

Comments
 (0)