Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将类型参数传递给附加的行为_C#_Wpf_Attachedbehaviors - Fatal编程技术网

C# 将类型参数传递给附加的行为

C# 将类型参数传递给附加的行为,c#,wpf,attachedbehaviors,C#,Wpf,Attachedbehaviors,我正在WPF应用程序中实现附加行为。我需要将类型参数传递给行为,这样我就可以调用SqliteBoundRow上的方法void NewRow(Table Table)。如果我在XAML中实例化一个对象,我会使用x:TypeArguments传递一个类型参数,但在设置附加行为时,我看不到这样做的方法,因为它使用静态属性 附加行为的代码如下所示: public abstract class SqliteBoundRow<T> where T : SqliteBoundRow<T>

我正在WPF应用程序中实现附加行为。我需要将类型参数传递给行为,这样我就可以调用
SqliteBoundRow
上的方法
void NewRow(Table Table)
。如果我在XAML中实例化一个对象,我会使用
x:TypeArguments
传递一个类型参数,但在设置附加行为时,我看不到这样做的方法,因为它使用静态属性

附加行为的代码如下所示:

public abstract class SqliteBoundRow<T> where T : SqliteBoundRow<T>
{
    public abstract void NewRow(Table<T> table);
}

public class DataGridBehavior<T> where T:SqliteBoundRow<T>
{
    public static readonly DependencyProperty IsEnabledProperty;
    static DataGridBehavior()
    {
        IsEnabledProperty = DependencyProperty.RegisterAttached("IsEnabled",
            typeof(bool), typeof(DataGridBehavior<T>),
            new FrameworkPropertyMetadata(false, OnBehaviorEnabled));
    }
    public static void SetIsEnabled(DependencyObject obj, bool value)
    {
        obj.SetValue(IsEnabledProperty, value);
    }
    public static bool GetIsEnabled(DependencyObject obj)
    {
        return (bool)obj.GetValue(IsEnabledProperty);
    }
    private static void OnBehaviorEnabled(DependencyObject dependencyObject,
        DependencyPropertyChangedEventArgs args)
    {
        var dg = dependencyObject as DataGrid;
        dg.InitializingNewItem += DataGrid_InitializingNewItem;
    }
    private static void DataGrid_InitializingNewItem(object sender,
        InitializingNewItemEventArgs e)
    {
        var table = (sender as DataGrid).ItemsSource as Table<T>;
        (e.NewItem as T).NewRow(table);
    }

}
<DataGrid DataGridBehavior.IsEnabled="True">
    <!-- DataGridBehavior needs a type parameter -->
</DataGrid>
公共抽象类SqliteBoundRow,其中T:SqliteBoundRow
{
公共摘要无效新行(表格);
}
公共类DataGridBehavior,其中T:SqliteBundRow
{
公共静态只读从属属性IsEnabledProperty;
静态DataGridBehavior()
{
IsEnabledProperty=DependencyProperty.RegisterAttached(“IsEnabled”,
typeof(bool),typeof(DataGridBehavior),
新的FrameworkPropertyMetadata(false,OnBehaviorEnabled));
}
公共静态无效设置已启用(DependencyObject对象,布尔值)
{
对象设置值(IsEnabledProperty,值);
}
公共静态bool GetIsEnabled(DependencyObject obj)
{
返回(bool)对象GetValue(IsEnabledProperty);
}
私有静态void OnBehaviorEnabled(DependencyObject DependencyObject,
DependencyPropertyChangedEventArgs(参数)
{
var dg=作为数据网格的dependencyObject;
dg.InitializingNewItem+=数据网格_InitializingNewItem;
}
私有静态void DataGrid_初始化newitem(对象发送方,
初始化NewItemEventArgs(e)
{
var table=(发送方为DataGrid)。ItemsSource为表;
(e.新项目为T)。新行(表);
}
}
XAML如下所示:

public abstract class SqliteBoundRow<T> where T : SqliteBoundRow<T>
{
    public abstract void NewRow(Table<T> table);
}

public class DataGridBehavior<T> where T:SqliteBoundRow<T>
{
    public static readonly DependencyProperty IsEnabledProperty;
    static DataGridBehavior()
    {
        IsEnabledProperty = DependencyProperty.RegisterAttached("IsEnabled",
            typeof(bool), typeof(DataGridBehavior<T>),
            new FrameworkPropertyMetadata(false, OnBehaviorEnabled));
    }
    public static void SetIsEnabled(DependencyObject obj, bool value)
    {
        obj.SetValue(IsEnabledProperty, value);
    }
    public static bool GetIsEnabled(DependencyObject obj)
    {
        return (bool)obj.GetValue(IsEnabledProperty);
    }
    private static void OnBehaviorEnabled(DependencyObject dependencyObject,
        DependencyPropertyChangedEventArgs args)
    {
        var dg = dependencyObject as DataGrid;
        dg.InitializingNewItem += DataGrid_InitializingNewItem;
    }
    private static void DataGrid_InitializingNewItem(object sender,
        InitializingNewItemEventArgs e)
    {
        var table = (sender as DataGrid).ItemsSource as Table<T>;
        (e.NewItem as T).NewRow(table);
    }

}
<DataGrid DataGridBehavior.IsEnabled="True">
    <!-- DataGridBehavior needs a type parameter -->
</DataGrid>


我目前的解决方案是将DataGridBehavior封装在一个指定类型参数的派生类中。

最简单的解决方案是声明另一个
附加属性
,但类型为
类型
,以便为您保存参数值。在这种情况下,您可以在启用附加属性之前设置
类型
属性:

<DataGrid DataGridBehavior.TypeParameter="{x:Type SomePrefix:SomeType}" 
    DataGridBehavior.IsEnabled="True" ... />


再次查看您的代码,您的
IsEnabled
属性似乎除了向表中添加新行之外,什么都不做。。。在这种情况下,没有理由不将其替换为
TypeParameter-Attached属性
,并使用该属性添加新行

我不认为WPF提供了一种优雅的语法方式来实现您想要的功能。所以我正要发布一个与谢里登的答案类似的答案。也就是说,您可以提供类型type的附加属性来确定泛型类型。然而,谢里登击败了我。下面是一些示例代码,介绍了如何使用反射来实现这一点:

Xaml


代码隐藏

public abstract class DataGridBehavior
{
    private static readonly ConcurrentDictionary<Type, DataGridBehavior> Behaviors = new ConcurrentDictionary<Type, DataGridBehavior>();
    public static readonly DependencyProperty IsEnabledProperty;
    public static readonly DependencyProperty InnerTypeProperty;
    static DataGridBehavior()
    {
        IsEnabledProperty = DependencyProperty.RegisterAttached("IsEnabled",
            typeof(bool), typeof(DataGridBehavior),
            new FrameworkPropertyMetadata(false, OnBehaviorEnabled));

        InnerTypeProperty = DependencyProperty.RegisterAttached("InnerType",
            typeof(Type), typeof(DataGridBehavior));
    }
    public static void SetIsEnabled(DependencyObject obj, bool value)
    {
        obj.SetValue(IsEnabledProperty, value);
    }
    public static bool GetIsEnabled(DependencyObject obj)
    {
        return (bool)obj.GetValue(IsEnabledProperty);
    }

    public static void SetInnerType(DependencyObject obj, Type value)
    {
        obj.SetValue(InnerTypeProperty, value);
    }
    public static Type GetInnerType(DependencyObject obj)
    {
        return (Type)obj.GetValue(InnerTypeProperty);
    }

    private static void OnBehaviorEnabled(DependencyObject dependencyObject,
          DependencyPropertyChangedEventArgs args)
    {
        var innerType = GetInnerType(dependencyObject);
        if (innerType == null)
            throw new Exception("Missing inner type");

        var behavior = Behaviors.GetOrAdd(innerType, GetBehavior);
        behavior.OnEnabled(dependencyObject);
    }

    private static DataGridBehavior GetBehavior(Type innerType)
    {
        var behaviorType = typeof(DataGridBehavior<>).MakeGenericType(innerType);
        var behavior = (DataGridBehavior)Activator.CreateInstance(behaviorType);
        return behavior;
    }

    protected abstract void OnEnabled(DependencyObject dependencyObject);

}

public class DataGridBehavior<T> : DataGridBehavior
    where T : SqliteBoundRow
{
    protected override void OnEnabled(DependencyObject dependencyObject)
    {
        //dg.InitializingNewItem += DataGrid_InitializingNewItem;
    }

    private static void DataGrid_InitializingNewItem(object sender,
        InitializingNewItemEventArgs e)
    {
        //var table = (sender as DataGrid).ItemsSource as Table<T>;
        //(e.NewItem as T).NewRow(table);
    }

}

public class SqliteBoundRow
{
}
公共抽象类DataGridBehavior
{
私有静态只读ConcurrentDictionary行为=新建ConcurrentDictionary();
公共静态只读从属属性IsEnabledProperty;
公共静态只读DependencyProperty InnerTypeProperty;
静态DataGridBehavior()
{
IsEnabledProperty=DependencyProperty.RegisterAttached(“IsEnabled”,
typeof(bool),typeof(DataGridBehavior),
新的FrameworkPropertyMetadata(false,OnBehaviorEnabled));
InnerTypeProperty=DependencyProperty.RegisterAttached(“InnerType”,
typeof(Type),typeof(DataGridBehavior));
}
公共静态无效设置已启用(DependencyObject对象,布尔值)
{
对象设置值(IsEnabledProperty,值);
}
公共静态bool GetIsEnabled(DependencyObject obj)
{
返回(bool)对象GetValue(IsEnabledProperty);
}
公共静态void SetInnerType(DependencyObject对象,类型值)
{
对象设置值(InnerTypeProperty,值);
}
公共静态类型GetInnerType(DependencyObject obj)
{
返回(类型)obj.GetValue(InnerTypeProperty);
}
私有静态void OnBehaviorEnabled(DependencyObject DependencyObject,
DependencyPropertyChangedEventArgs(参数)
{
var innerType=GetInnerType(dependencyObject);
if(innerType==null)
抛出新异常(“缺少内部类型”);
var behavior=Behaviors.GetOrAdd(innerType,GetBehavior);
行为.oneEnabled(dependencyObject);
}
私有静态DataGridBehavior GetBehavior(类型innerType)
{
var behaviorType=typeof(DataGridBehavior).MakeGenericType(innerType);
var behavior=(DataGridBehavior)Activator.CreateInstance(behaviorType);
回归行为;
}
受保护的抽象void OnEnabled(DependencyObject DependencyObject);
}
公共类DataGridBehavior:DataGridBehavior
其中T:SqliteBoundRow
{
受保护的覆盖无效OnEnabled(DependencyObject DependencyObject)
{
//dg.InitializingNewItem+=数据网格_InitializingNewItem;
}
私有静态void DataGrid_初始化newitem(对象发送方,
初始化NewItemEventArgs(e)
{
//var table=(发送方为DataGrid)。ItemsSource为表;
//(e.新项目为T)。新行(表);
}
}
公共类SqliteBoundRow
{
}

如果我定义了一个附加属性
TypeParameter
,那么我就不能在
DataGrid\u initializenewitem
中将其用作类型参数。也许这可以通过反射来完成,但我不想走这条路。这只是几行代码,今天早些时候我碰巧回答了一个问题,这个问题演示了如何从
类型
对象创建对象:。下面是一个