mirror of https://github.com/AMT-Cheif/Stylet.git
Revert the BindingProxy stuff
Trying to do this properly turns out to just be unworkable
This commit is contained in:
parent
35ecc551a3
commit
54cd9cf18f
|
@ -105,7 +105,6 @@
|
|||
<Compile Include="Xaml\ActionExtension.cs" />
|
||||
<Compile Include="BindableCollection.cs" />
|
||||
<Compile Include="BootstrapperBase.cs" />
|
||||
<Compile Include="Xaml\BindingProxy.cs" />
|
||||
<Compile Include="Xaml\BoolToVisibilityConverter.cs" />
|
||||
<Compile Include="Xaml\CommandAction.cs" />
|
||||
<Compile Include="Conductor.cs" />
|
||||
|
@ -135,7 +134,6 @@
|
|||
<Compile Include="Xaml\View.cs" />
|
||||
<Compile Include="ViewManager.cs" />
|
||||
<Compile Include="WindowManager.cs" />
|
||||
<Compile Include="Xaml\ViewModelBindingExtension.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Include="MessageBoxView.xaml">
|
||||
|
|
|
@ -320,15 +320,14 @@ namespace Stylet
|
|||
/// <param name="viewModel">ViewModel to bind the View to</param>
|
||||
public virtual void BindViewToModel(UIElement view, object viewModel)
|
||||
{
|
||||
// We used to set the View.ActionTarget here. However, we now have a system for falling back to the ViewModel
|
||||
// if the ActionTarget isn't found, so we'll use that instead.
|
||||
logger.Info("Setting {0}'s ActionTarget to {1}", view, viewModel);
|
||||
View.SetActionTarget(view, viewModel);
|
||||
|
||||
var viewAsFrameworkElement = view as FrameworkElement;
|
||||
if (viewAsFrameworkElement != null)
|
||||
{
|
||||
logger.Info("Setting {0}'s DataContext and ViewModel proxy to {1}", view, viewModel);
|
||||
logger.Info("Setting {0}'s DataContext to {1}", view, viewModel);
|
||||
viewAsFrameworkElement.DataContext = viewModel;
|
||||
View.SetViewModel(viewAsFrameworkElement, viewModel);
|
||||
}
|
||||
|
||||
var viewModelAsViewAware = viewModel as IViewAware;
|
||||
|
|
|
@ -4,8 +4,6 @@ using System.Reflection;
|
|||
using System.Runtime.ExceptionServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using System.Globalization;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Stylet.Xaml
|
||||
{
|
||||
|
@ -71,17 +69,13 @@ namespace Stylet.Xaml
|
|||
this.ActionNonExistentBehaviour = actionNonExistentBehaviour;
|
||||
this.logger = logger;
|
||||
|
||||
var multiBinding = new MultiBinding();
|
||||
multiBinding.Converter = new ActionTargetMultiValueConverter();
|
||||
multiBinding.Bindings.Add(new Binding()
|
||||
var binding = new Binding()
|
||||
{
|
||||
Path = new PropertyPath(View.ActionTargetProperty),
|
||||
Mode = BindingMode.OneWay,
|
||||
Source = this.Subject,
|
||||
});
|
||||
multiBinding.Bindings.Add(View.GetBindingToViewModel(this.Subject));
|
||||
|
||||
BindingOperations.SetBinding(this, targetProperty, multiBinding);
|
||||
};
|
||||
BindingOperations.SetBinding(this, targetProperty, binding);
|
||||
}
|
||||
|
||||
private void UpdateActionTarget(object oldTarget, object newTarget)
|
||||
|
@ -184,27 +178,5 @@ namespace Stylet.Xaml
|
|||
ExceptionDispatchInfo.Capture(e.InnerException).Throw();
|
||||
}
|
||||
}
|
||||
|
||||
private class ActionTargetMultiValueConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
// We expect 2 values: [0] is the actiontarget, and [1] is the viewmodel from resource
|
||||
Debug.Assert(values.Length == 2);
|
||||
|
||||
if (values[0] != View.InitialActionTarget)
|
||||
return values[0];
|
||||
|
||||
if (values[1] != null)
|
||||
return values[1];
|
||||
|
||||
return View.InitialActionTarget;
|
||||
}
|
||||
|
||||
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,21 +103,20 @@ namespace Stylet.Xaml
|
|||
|
||||
// Seems this is the case when we're in a template. We'll get called again properly in a second.
|
||||
// http://social.msdn.microsoft.com/Forums/vstudio/en-US/a9ead3d5-a4e4-4f9c-b507-b7a7d530c6a9/gaining-access-to-target-object-instead-of-shareddp-in-custom-markupextensions-providevalue-method?forum=wpf
|
||||
var targetObjectAsDependencyObject = valueService.TargetObject as DependencyObject;
|
||||
if (targetObjectAsDependencyObject == null)
|
||||
if (!(valueService.TargetObject is DependencyObject))
|
||||
return this;
|
||||
|
||||
var propertyAsDependencyProperty = valueService.TargetProperty as DependencyProperty;
|
||||
if (propertyAsDependencyProperty != null && propertyAsDependencyProperty.PropertyType == typeof(ICommand))
|
||||
{
|
||||
// If they're in design mode and haven't set View.ActionTarget, default to looking sensible
|
||||
return new CommandAction(targetObjectAsDependencyObject, this.Method, this.CommandNullTargetBehaviour, this.CommandActionNotFoundBehaviour);
|
||||
return new CommandAction((DependencyObject)valueService.TargetObject, this.Method, this.CommandNullTargetBehaviour, this.CommandActionNotFoundBehaviour);
|
||||
}
|
||||
|
||||
var propertyAsEventInfo = valueService.TargetProperty as EventInfo;
|
||||
if (propertyAsEventInfo != null)
|
||||
{
|
||||
var ec = new EventAction(targetObjectAsDependencyObject, propertyAsEventInfo.EventHandlerType, this.Method, this.EventNullTargetBehaviour, this.EventActionNotFoundBehaviour);
|
||||
var ec = new EventAction((DependencyObject)valueService.TargetObject, propertyAsEventInfo.EventHandlerType, this.Method, this.EventNullTargetBehaviour, this.EventActionNotFoundBehaviour);
|
||||
return ec.GetDelegate();
|
||||
}
|
||||
|
||||
|
@ -128,7 +127,7 @@ namespace Stylet.Xaml
|
|||
var parameters = propertyAsMethodInfo.GetParameters();
|
||||
if (parameters.Length == 2 && typeof(Delegate).IsAssignableFrom(parameters[1].ParameterType))
|
||||
{
|
||||
var ec = new EventAction(targetObjectAsDependencyObject, parameters[1].ParameterType, this.Method, this.EventNullTargetBehaviour, this.EventActionNotFoundBehaviour);
|
||||
var ec = new EventAction((DependencyObject)valueService.TargetObject, parameters[1].ParameterType, this.Method, this.EventNullTargetBehaviour, this.EventActionNotFoundBehaviour);
|
||||
return ec.GetDelegate();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace Stylet.Xaml
|
||||
{
|
||||
internal class BindingProxy : Freezable
|
||||
{
|
||||
protected override Freezable CreateInstanceCore()
|
||||
{
|
||||
return new BindingProxy();
|
||||
}
|
||||
|
||||
public object Data
|
||||
{
|
||||
get { return GetValue(DataProperty); }
|
||||
set { SetValue(DataProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty DataProperty =
|
||||
DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new PropertyMetadata(null));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converter which extracts the 'Data' property from a BindingProxy.
|
||||
/// </summary>
|
||||
internal class BindingProxyToValueConverter : IValueConverter
|
||||
{
|
||||
public static readonly BindingProxyToValueConverter Instance = new BindingProxyToValueConverter();
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
var proxy = value as BindingProxy;
|
||||
if (proxy != null)
|
||||
return proxy.Data;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,7 +3,6 @@ using System.Windows;
|
|||
using System.Windows.Data;
|
||||
using System.Windows.Markup;
|
||||
using System.Reflection;
|
||||
using Stylet.Logging;
|
||||
|
||||
namespace Stylet.Xaml
|
||||
{
|
||||
|
@ -12,11 +11,10 @@ namespace Stylet.Xaml
|
|||
/// </summary>
|
||||
public static class View
|
||||
{
|
||||
private static readonly ILogger logger = LogManager.GetLogger(typeof(View));
|
||||
|
||||
internal const string ViewManagerResourceKey = "b9a38199-8cb3-4103-8526-c6cfcd089df7";
|
||||
|
||||
internal const string ViewModelProxyResourceKey = "8b7cb732-8a14-4813-a580-b1f3cccea7b7";
|
||||
/// <summary>
|
||||
/// Key which will be used to retrieve the ViewManager associated with the current application, from application's resources
|
||||
/// </summary>
|
||||
public const string ViewManagerResourceKey = "b9a38199-8cb3-4103-8526-c6cfcd089df7";
|
||||
|
||||
/// <summary>
|
||||
/// Initial value of the ActionTarget property.
|
||||
|
@ -48,7 +46,7 @@ namespace Stylet.Xaml
|
|||
/// The object's ActionTarget. This is used to determine what object to call Actions on by the ActionExtension markup extension.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty ActionTargetProperty =
|
||||
DependencyProperty.RegisterAttached("ActionTarget", typeof(object), typeof(View), new FrameworkPropertyMetadata(InitialActionTarget));
|
||||
DependencyProperty.RegisterAttached("ActionTarget", typeof(object), typeof(View), new FrameworkPropertyMetadata(InitialActionTarget, FrameworkPropertyMetadataOptions.Inherits));
|
||||
|
||||
/// <summary>
|
||||
/// Fetch the ViewModel currently associated with a given object
|
||||
|
@ -107,81 +105,6 @@ namespace Stylet.Xaml
|
|||
}
|
||||
}));
|
||||
|
||||
// Dependency Properties with 'inherit' set are great, except when they're not. In particular, they lose their
|
||||
// value when you cross a boundary into an element which does not sit inside the visual (or logica?) tree.
|
||||
// For example, trying to get the value of a previously-set View.ActionTarget from a KeyBinding will fail, because
|
||||
// the KeyBinding does not sit inside either the visual or logical tree, and so View.ActionTarget loses its value.
|
||||
// However, there are ways around this. If you create an instance of an object inheriting from Freezable and set it
|
||||
// as a resource on some parent, you can later retrieve that resource even from children where inherited Dependency
|
||||
// Properties will fail, using {DynamicResource}.
|
||||
// Therefore. We have a class called BindingProxy, which has a single object 'Data' property and which inherits from
|
||||
// freezable. View.SetViewModel sets this as a resource (with key ViewModelProxyResourceKey) on whatever FrameworkElement
|
||||
// it's given, and sets the ViewModel as the 'Data' property. Later on, we can retrieve that BindingProxy from its
|
||||
// key, and extract the ViewModel from it.
|
||||
// Normally we'd be able to use FrameworkElement.SetResourceReference to emulate {DynamicResource} from code, but
|
||||
// irritatingly that's defined on FrameworkElement and not DependencyObject (even though it does nothing specific to
|
||||
// FrameworkElement), so won't work with e.g. KeyBinding (which inherits from DependencyObject but not FrameworkElement).
|
||||
// However, DynamicResourceExtension.ProvideValue doesn't actually require a service provider, so we can get away with
|
||||
// using it directly (it just wraps ResourceReferenceExpression, but that's internal, boo).
|
||||
// Because the result of {DynamicResource} can change, we need to assign it to a Dependency Property (we use
|
||||
// View.ViewModelProxy), and we return a binding which binds to that Dependency Property, and also has a converter
|
||||
// which extracts the 'Data' property from the BindingProxy.
|
||||
// The final step in the puzzle is that ActionBase will first look for a View.ActionTarget, and if not set, it will
|
||||
// then look for a ViewModel using View.GetBindingToViewModel.
|
||||
// The ViewModelExtension Markup Extension also uses this mechanism.
|
||||
|
||||
// To recap: if someone wants to get the ViewModel associated with a particular UI element, they can call
|
||||
// View.GetBindingToViewModel. This will create a lookup to our previously-stored BindingProxy resource (whose 'Data'
|
||||
// property is set to the ViewModel) using DynamicResourceExtension, and attach that to the View.ViewModelProxy
|
||||
// Dependency Property. It will then return a binding, which can be used to fetch the ViewModel. This mechanism
|
||||
// is used by {s:ViewModel}, and by ActionBase when an ActionTarget is otherwise not available.
|
||||
|
||||
/// <summary>
|
||||
/// Set the ViewModel which can be subsequently retrieved using {s:ViewModel}
|
||||
/// </summary>
|
||||
/// <param name="view">View to store the ViewModel for</param>
|
||||
/// <param name="viewModel">ViewModel to store</param>
|
||||
public static void SetViewModel(FrameworkElement view, object viewModel)
|
||||
{
|
||||
var bindingProxy = new BindingProxy()
|
||||
{
|
||||
Data = viewModel,
|
||||
};
|
||||
view.Resources[ViewModelProxyResourceKey] = bindingProxy;
|
||||
}
|
||||
|
||||
internal static void EnsureViewModelProxyValueSetUp(DependencyObject view)
|
||||
{
|
||||
if (view.GetValue(ViewModelProxyProperty) == null)
|
||||
{
|
||||
var resource = new DynamicResourceExtension(ViewModelProxyResourceKey).ProvideValue(null);
|
||||
view.SetValue(ViewModelProxyProperty, resource);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetch a binding which can be used to retrieve the ViewModel associated with a View
|
||||
/// </summary>
|
||||
/// <param name="view">View to fetch the ViewModel for</param>
|
||||
/// <returns>Binding which can retrieve the ViewModel</returns>
|
||||
public static Binding GetBindingToViewModel(DependencyObject view)
|
||||
{
|
||||
EnsureViewModelProxyValueSetUp(view);
|
||||
|
||||
var binding = new Binding()
|
||||
{
|
||||
Source = view,
|
||||
Path = new PropertyPath(ViewModelProxyProperty),
|
||||
Mode = BindingMode.OneWay,
|
||||
Converter = BindingProxyToValueConverter.Instance,
|
||||
};
|
||||
|
||||
return binding;
|
||||
}
|
||||
|
||||
internal static readonly DependencyProperty ViewModelProxyProperty =
|
||||
DependencyProperty.RegisterAttached("ViewModelProxy", typeof(BindingProxy), typeof(View), new PropertyMetadata(null));
|
||||
|
||||
/// <summary>
|
||||
/// Helper to set the Content property of a given object to a particular View
|
||||
/// </summary>
|
||||
|
|
|
@ -1,96 +0,0 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Markup;
|
||||
|
||||
namespace Stylet.Xaml
|
||||
{
|
||||
/// <summary>
|
||||
/// MarkupExtension which can retrieve the ViewModel for the current View, if available
|
||||
/// </summary>
|
||||
public class ViewModelBindingExtension : MarkupExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the path to the property
|
||||
/// </summary>
|
||||
public string Path { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the converter to use.
|
||||
/// </summary>
|
||||
public IValueConverter Converter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the culture in which to evaluate the converter.
|
||||
/// </summary>
|
||||
public CultureInfo ConverterCulture { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the parameter to pass to the Converter.
|
||||
/// </summary>
|
||||
public object ConverterParameter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value to use when the binding is unable to return a value
|
||||
/// </summary>
|
||||
public object FallbackValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a string that specifies how to format the binding if it displays the bound value as a string
|
||||
/// </summary>
|
||||
public string StringFormat { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value that is used in the target when the value of the source is null
|
||||
/// </summary>
|
||||
public object TargetNullValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new instance of the <see cref="ViewModelBindingExtension"/> class
|
||||
/// </summary>
|
||||
public ViewModelBindingExtension()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the Binding class with an initial path
|
||||
/// </summary>
|
||||
/// <param name="path">The initial Path for the binding</param>
|
||||
public ViewModelBindingExtension(string path)
|
||||
{
|
||||
this.Path = path;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When implemented in a derived class, returns an object that is provided as the
|
||||
/// value of the target property for this markup extension.
|
||||
/// </summary>
|
||||
/// <param name="serviceProvider">A service provider helper that can provide services for the markup extension.</param>
|
||||
/// <returns>The object value to set on the property where the extension is applied.</returns>
|
||||
public override object ProvideValue(IServiceProvider serviceProvider)
|
||||
{
|
||||
var valueService = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
|
||||
var targetObjectAsDependencyObject = valueService.TargetObject as DependencyObject;
|
||||
if (targetObjectAsDependencyObject == null)
|
||||
return this;
|
||||
|
||||
View.EnsureViewModelProxyValueSetUp(targetObjectAsDependencyObject);
|
||||
|
||||
var binding = new Binding()
|
||||
{
|
||||
Source = targetObjectAsDependencyObject,
|
||||
Path = new PropertyPath("(0).(1)." + this.Path, View.ViewModelProxyProperty, BindingProxy.DataProperty),
|
||||
Mode = BindingMode.OneWay,
|
||||
Converter = this.Converter,
|
||||
ConverterCulture = this.ConverterCulture,
|
||||
ConverterParameter = this.ConverterParameter,
|
||||
FallbackValue = this.FallbackValue,
|
||||
StringFormat = this.StringFormat,
|
||||
TargetNullValue = this.TargetNullValue,
|
||||
};
|
||||
|
||||
return binding.ProvideValue(serviceProvider);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,16 +2,16 @@
|
|||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:s="https://github.com/canton7/Stylet"
|
||||
Title="ShellView" Height="500" Width="500" SizeToContent="Height">
|
||||
Title="ShellView" Height="500" Width="500">
|
||||
<DockPanel LastChildFill="False">
|
||||
<GroupBox DockPanel.Dock="Top" Header="ShowDialog and DialogResult" Padding="10">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Command="{s:Action ShowDialogAndDialogResult}" Content="Show Dialog"/>
|
||||
<TextBlock Margin="50,0,0,0">Result: </TextBlock>
|
||||
<Button Command="{s:Action ShowDialogAndDialogResult}">Show Dialog</Button>
|
||||
<TextBlock Margin="50,0,0,0">Result:</TextBlock>
|
||||
<TextBlock Margin="10,0,0,0" Text="{Binding ShowDialogAndDialogResultDialogResult}"/>
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
|
||||
|
||||
<GroupBox DockPanel.Dock="Top" Header="Window Lifecycle" Padding="10">
|
||||
<Button Command="{s:Action ShowWindowLifecycle}">Show Window</Button>
|
||||
</GroupBox>
|
||||
|
@ -29,11 +29,10 @@
|
|||
<Button DockPanel.Dock="Top" Command="{s:Action TestDispatcher}">Test Dispatcher</Button>
|
||||
</DockPanel>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox DockPanel.Dock="Top" Header="ActionTarget" Padding="10">
|
||||
<DockPanel>
|
||||
<TextBlock DockPanel.Dock="Top" TextWrapping="WrapWithOverflow">
|
||||
Verify that pressing ctrl+s in the text box creates a dialog. Also verify that right-clicking in the text box and clicking the menu item shows a dialog.
|
||||
Verify that pressing ctrl+s in the text box creates a dialog. Also verify that right-clicking in the text box and clicking the menu item shows a dialog.
|
||||
</TextBlock>
|
||||
<TextBox DockPanel.Dock="Top">
|
||||
<TextBox.InputBindings>
|
||||
|
@ -45,14 +44,6 @@
|
|||
</ContextMenu>
|
||||
</TextBox.ContextMenu>
|
||||
</TextBox>
|
||||
<Button DockPanel.Dock="Top" s:View.ActionTarget="{Binding ChildViewModel}" Command="{s:Action Foo}">Click Me</Button>
|
||||
</DockPanel>
|
||||
</GroupBox>
|
||||
|
||||
<GroupBox DockPanel.Dock="Top" Header="{}{ViewModel}" Padding="10">
|
||||
<DockPanel DataContext="{x:Null}">
|
||||
<TextBlock DockPanel.Dock="Top">Ensure that the label below displays the text "Pass":</TextBlock>
|
||||
<TextBlock DockPanel.Dock="Top" Text="{s:ViewModelBinding ViewModelTestLabel}"/>
|
||||
</DockPanel>
|
||||
</GroupBox>
|
||||
</DockPanel>
|
||||
|
|
|
@ -68,16 +68,6 @@ namespace StyletIntegrationTests
|
|||
else
|
||||
this.windowManager.ShowMessageBox("Failure");
|
||||
}
|
||||
|
||||
public void ShowActionTargetSaved()
|
||||
{
|
||||
this.windowManager.ShowMessageBox("PASS!");
|
||||
}
|
||||
|
||||
public string ViewModelTestLabel
|
||||
{
|
||||
get { return "Pass"; }
|
||||
}
|
||||
}
|
||||
|
||||
public class ChildViewModel
|
||||
|
|
|
@ -304,13 +304,15 @@ namespace StyletUnitTests
|
|||
}
|
||||
|
||||
[Test]
|
||||
public void BindViewToModelDoesNotSetActionTarget()
|
||||
public void BindViewToModelSetsActionTarget()
|
||||
{
|
||||
var view = new UIElement();
|
||||
var model = new object();
|
||||
var viewManager = new AccessibleViewManager(type => null, new List<Assembly>());
|
||||
viewManager.BindViewToModel(view, new object());
|
||||
|
||||
Assert.AreEqual(View.InitialActionTarget, View.GetActionTarget(view));
|
||||
viewManager.BindViewToModel(view, model);
|
||||
|
||||
Assert.AreEqual(model, View.GetActionTarget(view));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
|
@ -5,9 +5,7 @@ using Stylet.Xaml;
|
|||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace StyletUnitTests
|
||||
{
|
||||
|
@ -27,19 +25,6 @@ namespace StyletUnitTests
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private class TestObjectWithDP : DependencyObject
|
||||
{
|
||||
public object DP
|
||||
{
|
||||
get { return (object)GetValue(DPProperty); }
|
||||
set { SetValue(DPProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty DPProperty =
|
||||
DependencyProperty.Register("DP", typeof(object), typeof(TestObjectWithDP), new PropertyMetadata(null));
|
||||
}
|
||||
|
||||
private Mock<IViewManager> viewManager;
|
||||
|
||||
[SetUp]
|
||||
|
@ -66,7 +51,7 @@ namespace StyletUnitTests
|
|||
public void ModelStores()
|
||||
{
|
||||
var obj = new FrameworkElement();
|
||||
obj.Resources.Add("b9a38199-8cb3-4103-8526-c6cfcd089df7", this.viewManager.Object);
|
||||
obj.Resources.Add(View.ViewManagerResourceKey, this.viewManager.Object);
|
||||
View.SetModel(obj, 5);
|
||||
Assert.AreEqual(5, View.GetModel(obj));
|
||||
}
|
||||
|
@ -75,7 +60,7 @@ namespace StyletUnitTests
|
|||
public void ChangingModelCallsOnModelChanged()
|
||||
{
|
||||
var obj = new FrameworkElement();
|
||||
obj.Resources.Add("b9a38199-8cb3-4103-8526-c6cfcd089df7", this.viewManager.Object);
|
||||
obj.Resources.Add(View.ViewManagerResourceKey, this.viewManager.Object);
|
||||
var model = new object();
|
||||
View.SetModel(obj, null);
|
||||
|
||||
|
@ -170,24 +155,5 @@ namespace StyletUnitTests
|
|||
var content = (TextBlock)element.Content;
|
||||
Assert.AreEqual("View for TestViewModel.SubViewModel", content.Text);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ViewModelCanBeRetrievedByChildren()
|
||||
{
|
||||
var view = new UserControl();
|
||||
var viewModel = new object();
|
||||
View.SetViewModel(view, viewModel);
|
||||
|
||||
// Use something that doesn't inherit attached properties
|
||||
var keyBinding = new KeyBinding();
|
||||
view.InputBindings.Add(keyBinding);
|
||||
|
||||
var binding = View.GetBindingToViewModel(keyBinding);
|
||||
|
||||
var receiver = new TestObjectWithDP();
|
||||
BindingOperations.SetBinding(receiver, TestObjectWithDP.DPProperty, binding);
|
||||
|
||||
Assert.AreEqual(viewModel, receiver.DP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue