Initial commit
This commit is contained in:
parent
7426826ccd
commit
322a458f32
|
@ -0,0 +1,16 @@
|
|||
namespace StyletDependentProperty.Test.BsClasses
|
||||
{
|
||||
class Bar : DependentPropertyChangedBase<Bar>
|
||||
{
|
||||
private readonly Foo _foo;
|
||||
|
||||
public Bar(Foo foo)
|
||||
{
|
||||
_foo = foo;
|
||||
DependOn(foo, x => x.Value).For(() => FooDependentValue);
|
||||
}
|
||||
|
||||
public string FooDependentValue => _foo.Value.ToUpper();
|
||||
public string UnrelatedValue { get; } = "unrelated";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
namespace StyletDependentProperty.Test.BsClasses
|
||||
{
|
||||
class Baz : DependentPropertyChangedBase<Baz>
|
||||
{
|
||||
private string _asd;
|
||||
|
||||
public Baz()
|
||||
{
|
||||
DependOn(x => x.Asd).For(x => x.Fgh);
|
||||
}
|
||||
|
||||
public string Asd
|
||||
{
|
||||
get { return _asd; }
|
||||
set
|
||||
{
|
||||
_asd = value;
|
||||
NotifyOfPropertyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public string Fgh => Asd.ToLower();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
namespace StyletDependentProperty.Test.BsClasses
|
||||
{
|
||||
class Baz2 : DependentPropertyChangedBase<Baz2>
|
||||
{
|
||||
private readonly Baz _baz;
|
||||
|
||||
public Baz2(Baz baz)
|
||||
{
|
||||
_baz = baz;
|
||||
DependOn(baz, x => x.Asd).For(my => my.Jkl);
|
||||
}
|
||||
|
||||
public string Jkl => _baz.Asd.ToUpper();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StyletDependentProperty.Test.BsClasses
|
||||
{
|
||||
using System.Linq.Expressions;
|
||||
|
||||
class Foo : DependentPropertyChangedBase<Foo>
|
||||
{
|
||||
private string _value;
|
||||
|
||||
public Foo(string value)
|
||||
{
|
||||
_value = value;
|
||||
DependOn(x => x.Value).For(() => CalculatedValue);
|
||||
|
||||
ParameterlessAccessorExpression = () => Value;
|
||||
}
|
||||
|
||||
public string Value
|
||||
{
|
||||
get { return _value; }
|
||||
set
|
||||
{
|
||||
_value = value;
|
||||
NotifyOfPropertyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public string CalculatedValue => Value.ToLower();
|
||||
public string UnrelatedValue { get; } = "unrelated";
|
||||
public Expression<Func<string>> ParameterlessAccessorExpression { get; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
namespace StyletDependentProperty.Test.BsClasses
|
||||
{
|
||||
class Summation : DependentPropertyChangedBase<Summation>
|
||||
{
|
||||
private int _a;
|
||||
private int _b;
|
||||
|
||||
public Summation()
|
||||
{
|
||||
DependOn(x => x.A).For(() => Sum);
|
||||
DependOn(x => x.B).For(() => Sum);
|
||||
}
|
||||
|
||||
public int A
|
||||
{
|
||||
get { return _a; }
|
||||
set
|
||||
{
|
||||
_a = value;
|
||||
NotifyOfPropertyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public int B
|
||||
{
|
||||
get { return _b; }
|
||||
set
|
||||
{
|
||||
_b = value;
|
||||
NotifyOfPropertyChange();
|
||||
}
|
||||
}
|
||||
|
||||
public int Sum => A + B;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
namespace StyletDependentProperty.Test
|
||||
{
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
using BsClasses;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
public class CrossObjectBindingTests : DependencyTestFixture
|
||||
{
|
||||
[TestMethod]
|
||||
public void BindOther()
|
||||
{
|
||||
var foo = new Foo("123");
|
||||
var bar = new Bar(foo);
|
||||
|
||||
AssertChange(foo, bar, x => x.FooDependentValue, () => foo.Value = "arbitrary");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
namespace StyletDependentProperty.Test
|
||||
{
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
public class DependencyTestFixture
|
||||
{
|
||||
protected void AssertChange<TDependency, TDependent>(TDependency master, TDependent slave, Expression<Func<TDependent, object>> property, Action when, bool shouldHappen = true)
|
||||
where TDependency : DependentPropertyChangedBase
|
||||
where TDependent : DependentPropertyChangedBase
|
||||
{
|
||||
var changed = false;
|
||||
var propName = DependencyHelper.GetPropertyAccessorName(property);
|
||||
|
||||
slave.PropertyChanged += (sender, args) => { changed |= args.PropertyName == propName; };
|
||||
|
||||
when();
|
||||
Assert.AreEqual(shouldHappen, changed);
|
||||
}
|
||||
|
||||
protected void AssertChange<TViewModel>(TViewModel self, Expression<Func<TViewModel, object>> property, Action when, bool shouldHappen = true)
|
||||
where TViewModel : DependentPropertyChangedBase
|
||||
=> AssertChange(self, self, property, when, shouldHappen);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("StyletDependentProperty.Test")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("99X")]
|
||||
[assembly: AssemblyProduct("StyletDependentProperty.Test")]
|
||||
[assembly: AssemblyCopyright("Copyright © 99X 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("e0a3b142-b780-4d88-b547-7e5cb21a6adf")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
@ -0,0 +1,34 @@
|
|||
namespace StyletDependentProperty.Test
|
||||
{
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
using BsClasses;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
public class PropertyLambdaTests
|
||||
{
|
||||
public object Derp { get; } = null;
|
||||
|
||||
[TestMethod]
|
||||
public void FindPropertyAccessorName()
|
||||
{
|
||||
var foo = new Foo("123");
|
||||
Assert.AreEqual("Value", DependencyHelper.GetPropertyAccessorName((Foo x) => x.Value));
|
||||
Assert.AreEqual("Derp", DependencyHelper.GetPropertyAccessorName(() => Derp));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void DeparameterizeExpression()
|
||||
{
|
||||
Expression<Func<Foo, string>> fooParameterizedAccessor = x => x.Value;
|
||||
|
||||
var foo = new Foo("abc");
|
||||
|
||||
Assert.AreEqual(
|
||||
foo.ParameterlessAccessorExpression.ToString(),
|
||||
DependencyHelper.ToNonParametricFuncExpression(fooParameterizedAccessor, foo).ToString());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
namespace StyletDependentProperty.Test
|
||||
{
|
||||
using BsClasses;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
[TestClass]
|
||||
public class SelfBindingTest : DependencyTestFixture
|
||||
{
|
||||
[TestMethod]
|
||||
public void BindSelfProperty()
|
||||
{
|
||||
var foo = new Foo("123");
|
||||
|
||||
AssertChange(foo, x => x.CalculatedValue, () => foo.Value = "arbitrary");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void UnrelatedSelfProperty()
|
||||
{
|
||||
var foo = new Foo("123");
|
||||
|
||||
AssertChange(foo, x => x.UnrelatedValue, () => foo.Value = "arbitrary", false);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void BindDualSelfProperty()
|
||||
{
|
||||
var summation = new Summation();
|
||||
|
||||
AssertChange(summation, x => x.Sum, () => summation.A = 1);
|
||||
AssertChange(summation, x => x.Sum, () => summation.B = 1);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void BindSelfPropertyIdentifiedByParametricExpression()
|
||||
{
|
||||
var baz = new Baz();
|
||||
AssertChange(baz, x => x.Fgh, () => baz.Asd = "arbitrary");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{E0A3B142-B780-4D88-B547-7E5CB21A6ADF}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>StyletDependentProperty.Test</RootNamespace>
|
||||
<AssemblyName>StyletDependentProperty.Test</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
|
||||
<IsCodedUITest>False</IsCodedUITest>
|
||||
<TestProjectType>UnitTest</TestProjectType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Stylet, Version=1.1.7.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Stylet.1.1.7\lib\net45\Stylet.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
</ItemGroup>
|
||||
<Choose>
|
||||
<When Condition="('$(VisualStudioVersion)' == '10.0' or '$(VisualStudioVersion)' == '') and '$(TargetFrameworkVersion)' == 'v3.5'">
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
|
||||
</ItemGroup>
|
||||
</When>
|
||||
<Otherwise>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework" />
|
||||
</ItemGroup>
|
||||
</Otherwise>
|
||||
</Choose>
|
||||
<ItemGroup>
|
||||
<Compile Include="BsClasses\Bar.cs" />
|
||||
<Compile Include="BsClasses\Baz.cs" />
|
||||
<Compile Include="BsClasses\Baz2.cs" />
|
||||
<Compile Include="BsClasses\Foo.cs" />
|
||||
<Compile Include="BsClasses\Summation.cs" />
|
||||
<Compile Include="DependencyTestFixture.cs" />
|
||||
<Compile Include="CrossObjectBindingTests.cs" />
|
||||
<Compile Include="PropertyLambdaTests.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SelfBindingTest.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\StyletDependentProperty\StyletDependentProperty.csproj">
|
||||
<Project>{7868f54a-12e7-4a92-8bf9-35f4f800cd32}</Project>
|
||||
<Name>StyletDependentProperty</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Choose>
|
||||
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.VisualStudio.QualityTools.CodedUITestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITest.Extension, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestTools.UITesting, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
</When>
|
||||
</Choose>
|
||||
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Stylet" version="1.1.7" targetFramework="net452" />
|
||||
</packages>
|
|
@ -0,0 +1,28 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.23107.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StyletDependentProperty", "StyletDependentProperty\StyletDependentProperty.csproj", "{7868F54A-12E7-4A92-8BF9-35F4F800CD32}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StyletDependentProperty.Test", "StyletDependentProperty.Test\StyletDependentProperty.Test.csproj", "{E0A3B142-B780-4D88-B547-7E5CB21A6ADF}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{7868F54A-12E7-4A92-8BF9-35F4F800CD32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7868F54A-12E7-4A92-8BF9-35F4F800CD32}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7868F54A-12E7-4A92-8BF9-35F4F800CD32}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7868F54A-12E7-4A92-8BF9-35F4F800CD32}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E0A3B142-B780-4D88-B547-7E5CB21A6ADF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E0A3B142-B780-4D88-B547-7E5CB21A6ADF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E0A3B142-B780-4D88-B547-7E5CB21A6ADF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E0A3B142-B780-4D88-B547-7E5CB21A6ADF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -0,0 +1,33 @@
|
|||
namespace StyletDependentProperty
|
||||
{
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
internal class DependencyBuilder<TDependencyViewModel, TDependencyProperty, TSelf> : IDependentPropertyLocator<TSelf>
|
||||
where TSelf : IDependencyRegistrar
|
||||
where TDependencyViewModel : DependentPropertyChangedBase
|
||||
{
|
||||
private readonly Expression<Func<TDependencyViewModel, TDependencyProperty>> _dependencyLocator;
|
||||
private readonly TDependencyViewModel _dependencyViewModel;
|
||||
private readonly TSelf _dependentViewModel;
|
||||
|
||||
public DependencyBuilder(TSelf dependentViewModel, TDependencyViewModel dependencyViewModel,
|
||||
Expression<Func<TDependencyViewModel, TDependencyProperty>> dependencyLocator)
|
||||
{
|
||||
_dependentViewModel = dependentViewModel;
|
||||
_dependencyViewModel = dependencyViewModel;
|
||||
_dependencyLocator = dependencyLocator;
|
||||
}
|
||||
|
||||
public void For<TDependentProperty>(Expression<Func<TDependentProperty>> dependentLocator)
|
||||
{
|
||||
_dependentViewModel.RegisterDependency(_dependencyViewModel, _dependencyLocator, dependentLocator);
|
||||
}
|
||||
|
||||
public void For<TDependentProperty>(Expression<Func<TSelf, TDependentProperty>> dependentLocator)
|
||||
{
|
||||
var adjustedDependentLocator = DependencyHelper.ToNonParametricFuncExpression(dependentLocator, _dependentViewModel);
|
||||
_dependentViewModel.RegisterDependency(_dependencyViewModel, _dependencyLocator, adjustedDependentLocator);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
namespace StyletDependentProperty
|
||||
{
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
internal static class DependencyHelper
|
||||
{
|
||||
public static Expression<Func<TOut>> ToNonParametricFuncExpression<TIn, TOut>(Expression<Func<TIn, TOut>> parametricExpression, TIn inValue)
|
||||
{
|
||||
var propertyName = ((parametricExpression.Body as MemberExpression)?.Member)?.Name;
|
||||
|
||||
if (string.IsNullOrEmpty(propertyName))
|
||||
throw new ArgumentException(nameof(parametricExpression));
|
||||
|
||||
return Expression.Lambda<Func<TOut>>(Expression.PropertyOrField(Expression.Constant(inValue, typeof (TIn)), propertyName));
|
||||
}
|
||||
|
||||
public static string GetPropertyAccessorName(Expression x)
|
||||
{
|
||||
string name = null;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (x is MemberExpression)
|
||||
{
|
||||
name = ((MemberExpression) x).Member.Name;
|
||||
break;
|
||||
}
|
||||
|
||||
if (x is LambdaExpression)
|
||||
{
|
||||
x = ((LambdaExpression) x).Body;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (x is MethodCallExpression)
|
||||
{
|
||||
x = ((MethodCallExpression) x).Arguments.First();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (x is UnaryExpression)
|
||||
{
|
||||
x = ((UnaryExpression) x).Operand;
|
||||
continue;
|
||||
}
|
||||
|
||||
throw new ArgumentException(x.GetType().GetFriendlyName());
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
public static string GetPropertyAccessorName<T>(Expression<Func<T>> e) => GetPropertyAccessorName(e.Body);
|
||||
public static string GetPropertyAccessorName<T1, T2>(Expression<Func<T1, T2>> e) => GetPropertyAccessorName(e.Body);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
namespace StyletDependentProperty
|
||||
{
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
using Stylet;
|
||||
|
||||
public abstract class DependentPropertyChangedBase : PropertyChangedBase
|
||||
{
|
||||
}
|
||||
|
||||
public class DependentPropertyChangedBase<TSelf> : DependentPropertyChangedBase, IDependencyRegistrar, IPropertyChangeSubscribable<TSelf>
|
||||
where TSelf : DependentPropertyChangedBase, IDependencyRegistrar
|
||||
{
|
||||
private TSelf Myself => this as TSelf;
|
||||
|
||||
public void RegisterDependency<TDependencyViewModel, TDependencyProperty, TDependentProperty>(
|
||||
TDependencyViewModel dependencyViewModel,
|
||||
Expression<Func<TDependencyViewModel, TDependencyProperty>> dependencyLocator,
|
||||
Expression<Func<TDependentProperty>> dependentLocator) where TDependencyViewModel : PropertyChangedBase
|
||||
{
|
||||
dependencyViewModel.Bind(dependencyLocator, (_, __) => { NotifyOfPropertyChange(dependentLocator); });
|
||||
}
|
||||
|
||||
public void OnChange<TDependencyProperty>(Expression<Func<TSelf, TDependencyProperty>> locator, Action callback)
|
||||
{
|
||||
var name = DependencyHelper.GetPropertyAccessorName(locator);
|
||||
Myself.Bind(locator, (sender, args) =>
|
||||
{
|
||||
if (args.PropertyName == name)
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
protected IDependentPropertyLocator<TSelf> DependOn<TDependencyProperty>(
|
||||
Expression<Func<TSelf, TDependencyProperty>> dependencyLocator)
|
||||
{
|
||||
return new DependencyBuilder<TSelf, TDependencyProperty, TSelf>(Myself, Myself, dependencyLocator);
|
||||
}
|
||||
|
||||
protected IDependentPropertyLocator<TSelf> DependOn<TDependencyViewModel, TDependencyProperty>(
|
||||
TDependencyViewModel dependencyViewModel,
|
||||
Expression<Func<TDependencyViewModel, TDependencyProperty>> dependencyLocator)
|
||||
where TDependencyViewModel : DependentPropertyChangedBase
|
||||
{
|
||||
return new DependencyBuilder<TDependencyViewModel, TDependencyProperty, TSelf>(Myself, dependencyViewModel, dependencyLocator);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
namespace StyletDependentProperty
|
||||
{
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
internal static class Extensions
|
||||
{
|
||||
public static string GetFriendlyName(this Type type)
|
||||
{
|
||||
var typeArgs = type.GetGenericArguments();
|
||||
if (!typeArgs.Any())
|
||||
return type.Name;
|
||||
|
||||
var genericArgString = string.Join(", ", typeArgs.Select(t => t.GetFriendlyName()));
|
||||
var typeName = type.Name.Substring(0, type.Name.IndexOf("`", StringComparison.InvariantCulture));
|
||||
|
||||
return $"{typeName}<{genericArgString}>";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
namespace StyletDependentProperty
|
||||
{
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
using Stylet;
|
||||
|
||||
public interface IDependencyRegistrar
|
||||
{
|
||||
void RegisterDependency<TDependencyViewModel, TDependencyProperty, TDependentProperty>(
|
||||
TDependencyViewModel dependencyViewModel,
|
||||
Expression<Func<TDependencyViewModel, TDependencyProperty>> dependencyLocator,
|
||||
Expression<Func<TDependentProperty>> dependentLocator)
|
||||
where TDependencyViewModel : PropertyChangedBase;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
namespace StyletDependentProperty
|
||||
{
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
public interface IDependentPropertyLocator<TSelf>
|
||||
{
|
||||
void For<TTarget>(Expression<Func<TTarget>> dependentLocator);
|
||||
void For<TTarget>(Expression<Func<TSelf, TTarget>> dependentLocator);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
namespace StyletDependentProperty
|
||||
{
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
public interface IPropertyChangeSubscribable<TSelf> where TSelf : DependentPropertyChangedBase, IDependencyRegistrar
|
||||
{
|
||||
void OnChange<TDependencyProperty>(Expression<Func<TSelf, TDependencyProperty>> locator, Action callback);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("StyletDependentProperty")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("99X")]
|
||||
[assembly: AssemblyProduct("StyletDependentProperty")]
|
||||
[assembly: AssemblyCopyright("Copyright © 99X 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("7868f54a-12e7-4a92-8bf9-35f4f800cd32")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
||||
[assembly: InternalsVisibleTo("StyletDependentProperty.Test")]
|
|
@ -0,0 +1,67 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{7868F54A-12E7-4A92-8BF9-35F4F800CD32}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>StyletDependentProperty</RootNamespace>
|
||||
<AssemblyName>StyletDependentProperty</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Stylet, Version=1.1.7.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Stylet.1.1.7\lib\net45\Stylet.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="DependencyBuilder.cs" />
|
||||
<Compile Include="DependencyHelper.cs" />
|
||||
<Compile Include="DependentPropertyChangedBase.cs" />
|
||||
<Compile Include="Extensions.cs" />
|
||||
<Compile Include="IDependencyRegistrar.cs" />
|
||||
<Compile Include="IDependentPropertyLocator.cs" />
|
||||
<Compile Include="IPropertyChangeSubscribable.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Stylet" version="1.1.7" targetFramework="net452" />
|
||||
</packages>
|
Loading…
Reference in New Issue