How to create converter to work like “FindAncestor

2019-06-09 07:43发布

问题:

I want to create a converter in which I will pass a type to find, in element's parent hierarchy & it should return true if such a type found, otherwise false.

So far, I tried below given code & it is working. but now only i have issue is it finds element parent hierarchy until element's parent is null. I want to give ancestor level for finding element in parent hierarchy. So How can I give Ancestor Level to converter??

I used LayoutHelper.cs Class to find element in parent hierarchy as given below.

public class LayoutHelper
{
    public static FrameworkElement FindElement(FrameworkElement treeRoot, Type type, int AncestorLevel)
    {
        FrameworkElement parentElement = VisualTreeHelper.GetParent(treeRoot) as FrameworkElement;
        int level = 1;
        while (parentElement != null && level <= AncestorLevel)
        {
            if (parentElement.GetType() == type)
                return parentElement;
            else
                parentElement = VisualTreeHelper.GetParent(parentElement) as FrameworkElement;
            level++;
        }
        return null;
    }
}

IsTypeFoundConverter.cs :-

public class IsTypeFoundConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        FrameworkElement element = value as FrameworkElement;
        Type type = parameter as Type;
        if (element != null && type != null)
        {
            element = LayoutHelper.FindElement(element, type,5);
            if (element != null)
                return true;
        }
        return false;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value;
    }
}

DataTrigger with IsTypeFoundConverter :

 <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self} ,Converter={StaticResource isTypeFoundConverter}, ConverterParameter={x:Type Type_To_Find}}" Value="false">
        <!--Setters-->
  </DataTrigger>

Here, In data trigger how can I pass AncestorLevel to converter so I can only find element upto that level??

Thanks, Amol bavannavar

回答1:

Declare a type to contain converter parameters:

public sealed class MyConverterParameter
{
    public Type AncestorType { get; set; }
    public int AncestorLevel { get; set; }
}

Re-write converter to use this type:

public sealed class MyConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var myParameter = (MyConverterParameter)parameter;

        // other converter stuff here
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var myParameter = (MyConverterParameter)parameter;

        // other converter stuff here
    }
}

Declare additional resource in XAML, e.g.:

        <DataTemplate>
            <DataTemplate.Resources>
                <local:MyConverter x:Key="MyConverterKey"/>
                <local:MyConverterParameter x:Key="MyConverterParameterKey" AncestorType="{x:Type Type-To-Find}" AncestorLevel="1"/>
            </DataTemplate.Resources>

            <!-- DataTemplate tree -->

            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding Path-To-Bind-To, Converter={StaticResource MyConverterKey}, ConverterParameter={StaticResource MyConverterParameterKey}}" Value="Value-To-Fire-Trigger">
                    <!-- Setters -->
                </DataTrigger>
            </DataTemplate.Triggers>
        </DataTemplate>

P.S. Why FindAncestor mode for RealtiveSource doesn't suits you?