!!! Обновление !!!
Хорошо, я взял это немного дальше.Я расширил расширение для выполнения всей работы, включая настройку коллекции Triggers.
TriggerCollectionExtension Расширение, которое выполняет всю тяжелую работу.Примечание. При первом вызове ProvideValue будет происходить загрузка стиля, поэтому TargetValue является сеттером.
[ContentProperty("Triggers")]
public class TriggerCollectionExtension : MarkupExtension
{
public string EventName { get; set; }
public string CommandName { get; set; }
public object CommandParameter { get; set; }
public System.Windows.Interactivity.TriggerCollection Triggers { get; private set;}
public TriggerCollectionExtension()
{
var trigCollectionType =
typeof(System.Windows.Interactivity.TriggerCollection);
var triggers = (System.Windows.Interactivity.TriggerCollection)
trigCollectionType.GetConstructor(
BindingFlags. NonPublic | BindingFlags. Instance,
null, Type.EmptyTypes, null).Invoke (null);
// Cheat to get around this problem.
// must have IsFrozen set to false to modify
var methCreateCore = trigCollectionType.GetMethod("CreateInstanceCore",
BindingFlags.NonPublic | BindingFlags.Instance);
var cloneTriggers =
(System.Windows.Interactivity.TriggerCollection)
methCreateCore.Invoke(triggers, null);
this.Triggers = cloneTriggers;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
var target = serviceProvider.GetService(typeof(IProvideValueTarget)) as
IProvideValueTarget;
// The first time this is called is when loading the style.
// At that point the TargetObject is of type Setter.
// Return this (The MarkupExtension) and it will be reevaluated when the style
// is applied.
var hostcontrol = target.TargetObject as Control;
if (hostcontrol != null)
{
var cloneTriggers = this.Triggers;
var eventTrigger = new EventTrigger(this.EventName);
var trigbase = eventTrigger as TriggerBase;
trigbase.Attach(hostcontrol);
var commandAction = new CommandAction(hostcontrol, this.CommandName,
this.CommandParameter);
eventTrigger.Actions.Add(commandAction);
cloneTriggers.Add(eventTrigger);
Interaction.SetShadowTriggers(hostcontrol, this.Triggers);
return null;
}
else
{
return this;
}
return null;
}
}
Взаимодействие Повторное владение / предоставление TriggersCollection.
<!-- language: c# -->
/// <summary>
/// Helps workaround the bug in the deployed interaction DLL.
/// The DependencyProperty is registered as ShadowTriggers and the Setter Getter is
/// SetTriggers() GetTriggers().
/// The result is compile error for XAML if anything but Shadowtriggers is used and
/// runtime error.
/// </summary>
public static class Interaction
{
static Interaction()
{
var interActionType = typeof(System.Windows.Interactivity.Interaction);
var triggersProperty = (DependencyProperty)interActionType.InvokeMember(
"TriggersProperty",
BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.GetField,
null, null, null);
ShadowTriggersProperty = triggersProperty.AddOwner(typeof(Interaction));
}
public static readonly DependencyProperty ShadowTriggersProperty;
public static System.Windows.Interactivity.TriggerCollection
GetShadowTriggers(DependencyObject d)
{
return
(System.Windows.Interactivity.TriggerCollection)
d.GetValue(ShadowTriggersProperty);
}
public static void
SetShadowTriggers(
DependencyObject d,
System.Windows.Interactivity.TriggerCollection value)
{
d.SetValue(ShadowTriggersProperty, value);
}
}
CommandAction Пользовательское действие TriggerAction, которое ищет Команду в DataContext.
<!-- language: c# -->
public class CommandAction : TriggerAction<FrameworkElement>
{
FrameworkElement control;
private string commandName;
object commandParameter;
private ICommand actualCommand;
public CommandAction(FrameworkElement control, string commandName,
object commandParameter)
{
this.control = control;
this.commandName = commandName;
this.commandParameter = commandParameter;
object datacontext;
if (this.FindDataContext(this.control, out datacontext))
{
var datacontextType = datacontext.GetType();
var propCommand = datacontextType.GetProperty(this.commandName);
this.actualCommand = propCommand.GetValue(datacontext, null) as ICommand;
}
}
private bool FindDataContext(FrameworkElement control, out object datacontext)
{
datacontext = default(object);
var parent = VisualTreeHelper.GetParent(control);
while (parent != null)
{
var parentFrame = parent as FrameworkElement;
if (parentFrame != null)
{
datacontext = parentFrame.DataContext;
if (datacontext != null)
{
return true;
}
}
var parentFrameContent = parent as FrameworkContentElement;
if (parentFrameContent != null)
{
datacontext = parentFrameContent.DataContext;
if (datacontext != null)
{
return true;
}
}
parent = VisualTreeHelper.GetParent(parent);
}
return false;
}
protected override void Invoke(object parameter)
{
if (this.actualCommand != null)
{
if (this.actualCommand.CanExecute(parameter))
{
this.actualCommand.Execute(parameter);
}
}
}
}
Wow-ридер, впервые публикующий код.Наконец-то я понял, почему код не всегда так хорошо вырезан и вставлен.Чтобы отправить это обновление потребовалось очень много попыток.
Я уверен, что существуют такие причины, как дисковое пространство, анализ или скорость рендеринга, и редактор поддерживает состояние при неудачной отправке.