mirror of https://github.com/AMT-Cheif/Stylet.git
YAY IT'S WORKING
This commit is contained in:
parent
f4bf876c6b
commit
540482a5f4
|
@ -246,7 +246,7 @@ namespace Stylet
|
|||
if (viewAsFrameworkElement != null)
|
||||
{
|
||||
logger.Info("Setting {0}'s DataContext to {1}", view, viewModel);
|
||||
View.SetDataContext(viewAsFrameworkElement, viewModel);
|
||||
viewAsFrameworkElement.DataContext = viewModel;
|
||||
}
|
||||
|
||||
var viewModelAsViewAware = viewModel as IViewAware;
|
||||
|
|
|
@ -4,6 +4,7 @@ using System.Reflection;
|
|||
using System.Runtime.ExceptionServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Stylet.Xaml
|
||||
{
|
||||
|
@ -69,13 +70,29 @@ namespace Stylet.Xaml
|
|||
this.ActionNonExistentBehaviour = actionNonExistentBehaviour;
|
||||
this.logger = logger;
|
||||
|
||||
var binding = new Binding()
|
||||
var multiBinding = new MultiBinding();
|
||||
multiBinding.Converter = new ActionTargetMultiValueConverter();
|
||||
multiBinding.Bindings.Add(new Binding()
|
||||
{
|
||||
Path = new PropertyPath(View.ActionTargetProperty),
|
||||
Mode = BindingMode.OneWay,
|
||||
Source = this.Subject,
|
||||
};
|
||||
BindingOperations.SetBinding(this, targetProperty, binding);
|
||||
});
|
||||
multiBinding.Bindings.Add(new Binding()
|
||||
{
|
||||
Path = new PropertyPath(View.BackupActionTargetBindingProxyProperty),
|
||||
Mode = BindingMode.OneWay,
|
||||
Source = this.Subject,
|
||||
Converter = new BindingProxyToValueConverter(),
|
||||
});
|
||||
|
||||
//var binding = new Binding()
|
||||
//{
|
||||
// Path = new PropertyPath(View.ActionTargetProperty),
|
||||
// Mode = BindingMode.OneWay,
|
||||
// Source = this.Subject,
|
||||
//};
|
||||
BindingOperations.SetBinding(this, targetProperty, multiBinding);
|
||||
}
|
||||
|
||||
private void UpdateActionTarget(object oldTarget, object newTarget)
|
||||
|
@ -196,5 +213,24 @@ namespace Stylet.Xaml
|
|||
ExceptionDispatchInfo.Capture(e.InnerException).Throw();
|
||||
}
|
||||
}
|
||||
|
||||
private class ActionTargetMultiValueConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
foreach (var value in values)
|
||||
{
|
||||
if (value != View.InitialActionTarget)
|
||||
return value;
|
||||
}
|
||||
|
||||
return View.InitialActionTarget;
|
||||
}
|
||||
|
||||
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,20 +103,26 @@ 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
|
||||
if (!(valueService.TargetObject is DependencyObject))
|
||||
var targetObjectAsDependencyObject = valueService.TargetObject as DependencyObject;
|
||||
if (targetObjectAsDependencyObject == null)
|
||||
return this;
|
||||
|
||||
// In some cases, the View.ActionTarget attached property won't be propagated - think popups, context menus, KeyBindings, etc
|
||||
// In this case, we can grab a reference to the last-set View.ActionTarget using the dynamic resources mechanism
|
||||
var resourceReference = new DynamicResourceExtension(View.ActionTargetProxyResourceKey).ProvideValue(serviceProvider);
|
||||
targetObjectAsDependencyObject.SetValue(View.BackupActionTargetBindingProxyProperty, resourceReference);
|
||||
|
||||
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((DependencyObject)valueService.TargetObject, this.Method, this.CommandNullTargetBehaviour, this.CommandActionNotFoundBehaviour);
|
||||
return new CommandAction(targetObjectAsDependencyObject, this.Method, this.CommandNullTargetBehaviour, this.CommandActionNotFoundBehaviour);
|
||||
}
|
||||
|
||||
var propertyAsEventInfo = valueService.TargetProperty as EventInfo;
|
||||
if (propertyAsEventInfo != null)
|
||||
{
|
||||
var ec = new EventAction((DependencyObject)valueService.TargetObject, propertyAsEventInfo.EventHandlerType, this.Method, this.EventNullTargetBehaviour, this.EventActionNotFoundBehaviour);
|
||||
var ec = new EventAction(targetObjectAsDependencyObject, propertyAsEventInfo.EventHandlerType, this.Method, this.EventNullTargetBehaviour, this.EventActionNotFoundBehaviour);
|
||||
return ec.GetDelegate();
|
||||
}
|
||||
|
||||
|
@ -127,7 +133,7 @@ namespace Stylet.Xaml
|
|||
var parameters = propertyAsMethodInfo.GetParameters();
|
||||
if (parameters.Length == 2 && typeof(Delegate).IsAssignableFrom(parameters[1].ParameterType))
|
||||
{
|
||||
var ec = new EventAction((DependencyObject)valueService.TargetObject, parameters[1].ParameterType, this.Method, this.EventNullTargetBehaviour, this.EventActionNotFoundBehaviour);
|
||||
var ec = new EventAction(targetObjectAsDependencyObject, parameters[1].ParameterType, this.Method, this.EventNullTargetBehaviour, this.EventActionNotFoundBehaviour);
|
||||
return ec.GetDelegate();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace Stylet.Xaml
|
||||
{
|
||||
|
@ -23,4 +25,21 @@ namespace Stylet.Xaml
|
|||
public static readonly DependencyProperty DataProperty =
|
||||
DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new PropertyMetadata(null));
|
||||
}
|
||||
|
||||
internal class BindingProxyToValueConverter : IValueConverter
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,6 @@ namespace Stylet.Xaml
|
|||
|
||||
internal const string ActionTargetProxyResourceKey = "8b7cb732-8a14-4813-a580-b1f3cccea7b7";
|
||||
|
||||
internal const string DataContextProxyResourceKey = "982a3cb4-68b8-464f-9f65-8835d86d94dd";
|
||||
|
||||
/// <summary>
|
||||
/// Initial value of the ActionTarget property.
|
||||
/// This can be used as a marker - if the property has this value, it hasn't yet been assigned to anything else.
|
||||
|
@ -34,23 +32,7 @@ namespace Stylet.Xaml
|
|||
/// <returns>ActionTarget associated with the given object</returns>
|
||||
public static object GetActionTarget(DependencyObject obj)
|
||||
{
|
||||
var actionTarget = obj.GetValue(ActionTargetProperty);
|
||||
|
||||
if (actionTarget == InitialActionTarget)
|
||||
{
|
||||
var frameworkElement = obj as FrameworkElement;
|
||||
if (frameworkElement != null)
|
||||
{
|
||||
var bindingProxy = frameworkElement.TryFindResource(ActionTargetProxyResourceKey) as BindingProxy;
|
||||
if (bindingProxy != null)
|
||||
{
|
||||
logger.Info("ActionTarget not set on object {0}, but a BindingProxy containing an ActionTarget was, so using that", obj);
|
||||
actionTarget = bindingProxy.Data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return actionTarget;
|
||||
return obj.GetValue(ActionTargetProperty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -74,14 +56,22 @@ namespace Stylet.Xaml
|
|||
if (frameworkElement == null)
|
||||
return;
|
||||
|
||||
// Don't set if it's been set already
|
||||
var currentValue = (BindingProxy)d.GetValue(BackupActionTargetBindingProxyProperty);
|
||||
if (currentValue != null && currentValue.Data == e.NewValue)
|
||||
return;
|
||||
|
||||
var bindingProxy = new BindingProxy()
|
||||
{
|
||||
Data = e.NewValue,
|
||||
};
|
||||
bindingProxy.Freeze();
|
||||
frameworkElement.Resources[ActionTargetProxyResourceKey] = bindingProxy;
|
||||
}));
|
||||
|
||||
internal static readonly DependencyProperty BackupActionTargetBindingProxyProperty =
|
||||
DependencyProperty.RegisterAttached("BackupActionTargetBindingProxy", typeof(BindingProxy), typeof(View), new PropertyMetadata(null));
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Fetch the ViewModel currently associated with a given object
|
||||
/// </summary>
|
||||
|
@ -139,44 +129,6 @@ namespace Stylet.Xaml
|
|||
}
|
||||
}));
|
||||
|
||||
|
||||
internal static void SetDataContext(FrameworkElement obj, object value)
|
||||
{
|
||||
obj.DataContext = value;
|
||||
var bindingProxy = new BindingProxy()
|
||||
{
|
||||
Data = value,
|
||||
};
|
||||
obj.Resources[DataContextProxyResourceKey] = bindingProxy;
|
||||
}
|
||||
|
||||
public static bool GetRestoreDataContext(DependencyObject obj)
|
||||
{
|
||||
return (bool)obj.GetValue(RestoreDataContextProperty);
|
||||
}
|
||||
|
||||
public static void SetRestoreDataContext(DependencyObject obj, bool value)
|
||||
{
|
||||
obj.SetValue(RestoreDataContextProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty RestoreDataContextProperty =
|
||||
DependencyProperty.RegisterAttached("RestoreDataContext", typeof(bool), typeof(View), new PropertyMetadata(false, (d, e) =>
|
||||
{
|
||||
if (!(e.NewValue is bool) || !(bool)e.NewValue)
|
||||
return;
|
||||
|
||||
var frameworkElement = d as FrameworkElement;
|
||||
if (frameworkElement == null)
|
||||
return;
|
||||
|
||||
var bindingProxy = frameworkElement.Resources[DataContextProxyResourceKey] as BindingProxy;
|
||||
if (bindingProxy == null)
|
||||
return;
|
||||
|
||||
frameworkElement.DataContext = bindingProxy.Data;
|
||||
}));
|
||||
|
||||
/// <summary>
|
||||
/// Helper to set the Content property of a given object to a particular View
|
||||
/// </summary>
|
||||
|
|
|
@ -6,13 +6,7 @@
|
|||
<DockPanel LastChildFill="False">
|
||||
<GroupBox DockPanel.Dock="Top" Header="ShowDialog and DialogResult" Padding="10">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Command="{s:Action ShowDialogAndDialogResult}" Content="Show Dialog">
|
||||
<Button.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="Foo" Command="{s:Action Foo}"/>
|
||||
</ContextMenu>
|
||||
</Button.ContextMenu>
|
||||
</Button>
|
||||
<Button Command="{s:Action ShowDialogAndDialogResult}" Content="Show Dialog"/>
|
||||
<TextBlock Margin="50,0,0,0">Result: </TextBlock>
|
||||
<TextBlock Margin="10,0,0,0" Text="{Binding ShowDialogAndDialogResultDialogResult}"/>
|
||||
</StackPanel>
|
||||
|
@ -38,11 +32,18 @@
|
|||
|
||||
<GroupBox DockPanel.Dock="Top" Header="ActionTarget" Padding="10">
|
||||
<DockPanel>
|
||||
<TextBlock DockPanel.Dock="Top">Verify that pressing ctrl+s in the text box creates a dialog</TextBlock>
|
||||
<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.
|
||||
</TextBlock>
|
||||
<TextBox DockPanel.Dock="Top">
|
||||
<TextBox.InputBindings>
|
||||
<KeyBinding Key="S" Modifiers="Ctrl" Command="{s:Action ShowActionTargetSaved}"/>
|
||||
</TextBox.InputBindings>
|
||||
<TextBox.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="Click Here" Command="{s:Action ShowActionTargetSaved}"/>
|
||||
</ContextMenu>
|
||||
</TextBox.ContextMenu>
|
||||
</TextBox>
|
||||
</DockPanel>
|
||||
</GroupBox>
|
||||
|
|
Loading…
Reference in New Issue