Question

Est-il possible et si oui, quelle est la meilleure façon de mettre en œuvre la structure hiérarchique suivante dans un silverlight (4) contrôle TreeView? (Lorsque le point et le groupe sont des classes qui peuvent exister dans l'arbre).


Group
|
|-Item
|
|-Group
| |
| |-Item
| |
| |-Item
|
|-Item

La structure pourrait bien sûr être arbitrairement plus complexe que cela, si nécessaire.

HierarchicalDataTemplates semblent être la façon d'aborder, mais je suis particulièrement mal à comprendre comment je pourrais appliquer le modèle d'interpréter les différentes classes correctement.

Une question similaire a été posée pour WPF, la réponse que fait usage de la propriété TargetType sur le HierarchicalDataTemplate, mais je suis certain que cette propriété est disponible dans la version silverlight puisque je ne semble pas y avoir accès en mon environnement.

Était-ce utile?

La solution

Pour Silverlight, vous pourriez avoir besoin de créer un convertisseur pour aider à le faire. Par exemple, un « type cible sélecteur de modèle de données » ou similaire.

Bien que vous pouvez obtenir plus avancée, voici un exemple du cadre de test unitaire Silverlight qui vous permet de donner des exemples de modèles de données pour les types codés en dur. Une version généralisée pourrait probablement être en 20 minutes environ.

Pour l'utiliser, vous souhaitez fournir des exemples de modèles de données -. Dans votre cas cependant, vous auriez probablement besoin de les rendre hiérarchique

<local:DataTemplateSelector 
    x:Key="DetailsViewDataTemplate"
    DefaultDataTemplate="{StaticResource DefaultDataTemplate}"
    TestMethodTemplate="{StaticResource TestMethodDataTemplate}"
    TestClassTemplate="{StaticResource TestClassDataTemplate}"/>

Et voici la mise en œuvre:

/// <summary>
/// A specialized data template selector.
/// </summary>
public sealed class DataTemplateSelector : IValueConverter
{
    /// <summary>
    /// Gets or sets the default data template.
    /// </summary>
    public DataTemplate DefaultDataTemplate { get; set; }

    /// <summary>
    /// Gets or sets the test method template.
    /// </summary>
    public DataTemplate TestMethodTemplate { get; set; }

    /// <summary>
    /// Gets or sets the test class template.
    /// </summary>
    public DataTemplate TestClassTemplate { get; set; }

    /// <summary>
    /// Initializes a new instance of the DataTemplateSelector type.
    /// </summary>
    public DataTemplateSelector()
    {
    }

    /// <summary>
    /// Convert a value to a data template.
    /// </summary>
    /// <param name="value">The value.</param>
    /// <param name="targetType">The target parameter.</param>
    /// <param name="parameter">ConverterParameter value.</param>
    /// <param name="culture">The culture parameter.</param>
    /// <returns>Returns the object.</returns>
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value != null)
        {
            Type type = value.GetType();

            if (typeof(TestMethodData).TypeHandle == type.TypeHandle)
            {
                return TestMethodTemplate;
            }
            else if (typeof(TestClassData).TypeHandle == type.TypeHandle)
            {
                return TestClassTemplate;
            }
        }

        return DefaultDataTemplate;
    }

    /// <summary>
    /// No 2-way databinding support.
    /// </summary>
    /// <param name="value">The value.</param>
    /// <param name="targetType">The target parameter.</param>
    /// <param name="parameter">ConverterParameter value.</param>
    /// <param name="culture">The culture parameter.</param>
    /// <returns>Returns the object.</returns>
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return null;
    }
}

Autres conseils

Ma mise en œuvre

<UserControl.Resources>

    <DataTemplate x:Key="DefaultDataTemplate">
        <TextBlock Text="Default"/>
    </DataTemplate>

    <DataTemplate x:Key="ConditionDataTemplate">
        <Grid>
            <TextBlock Text="{Binding ConditionType}" Margin="5" Width="100"/>
        </Grid>
    </DataTemplate>

    <DataTemplate x:Key="ButtonDataTemplate">
        <Grid>
            <Button Content="{Binding Name}"/>
        </Grid>
    </DataTemplate>

    <DataTemplate x:Key="FieldDataTemplate">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <ComboBox Grid.Column="0" ItemsSource="{Binding Fields}" SelectedItem="{Binding Name,Mode=TwoWay}" Margin="5,0,5,0"/>
            <ComboBox Grid.Column="1" ItemsSource="{Binding ConditionTypes}" SelectedItem="{Binding ConditionType,Mode=TwoWay}" Margin="5,0,5,0"/>
            <TextBox Grid.Column="2" Text="{Binding Value, Mode=TwoWay}" Margin="5" Width="100"/>
        </Grid>
    </DataTemplate>

    <local:DataTemplateSelector 
            x:Key="DetailsViewDataTemplate"
            DefaultDataTemplate="{StaticResource DefaultDataTemplate}"
            ConditionDataTemplate="{StaticResource ConditionDataTemplate}"
            FieldDataTemplate="{StaticResource FieldDataTemplate}"
            ButtonDataTemplate="{StaticResource ButtonDataTemplate}"/>
</UserControl.Resources>
<Grid>
    <sdk:TreeView ItemsSource="{Binding Tree}">
        <sdk:TreeView.ItemTemplate>
            <sdk:HierarchicalDataTemplate ItemsSource="{Binding ChildNodes}">
                    <ContentControl ContentTemplate="{Binding Converter={StaticResource DetailsViewDataTemplate}}" Content="{Binding}"/>
            </sdk:HierarchicalDataTemplate>
        </sdk:TreeView.ItemTemplate>
    </sdk:TreeView>
</Grid>

MainClass

    public class MainPageModel : BaseModel
{
    private ObservableCollection<object> _Tree;
    public ObservableCollection<object> Tree
    {
        get
        {
            return _Tree;
        }
        set
        {
            _Tree = value;
            Notify("Tree");
        }
    }

    public MainPageModel()
    {
        Tree = new ObservableCollection<object>();
        Tree.Add(new Condition()
        {
            ConditionType = "OR",
                ChildNodes = new ObservableCollection<object>()
                {
                    new Field()
                        {
                            Name = "Поле 2", 
                            ConditionType = "=",
                            Value = "3"
                    },
                    new Field()
                        {
                            Name = "Поле 3",
                            ConditionType = ">",
                            Value = "3"
                    },
                    new Field()
                        {
                            Name = "Поле 4",
                            ConditionType = "<",
                            Value = "3"
                    },
                    new Condition() 
                    { 
                        ConditionType = "AND" ,
                    ChildNodes = new ObservableCollection<object>()
                    {
                        new Field()
                            {
                                Name = "Поле 2",
                                ConditionType = "=", 
                                Value = "3"
                            },
                        new Field()
                            {
                                Name = "Поле 3",
                                ConditionType = ">",
                                Value = "3"

                        },
                        new Field()
                            {
                                Name = "Поле 4",
                                ConditionType = "<",
                                Value = "3"
                        },
                        new Button()
                        {
                                Name = "Добавить"
                        }
                    }
                }
            }
            });
        Notify("Tree");
    }
}

public static class PickList
{
    public static ObservableCollection<string> Fields
    {
        get
        {
            return new ObservableCollection<string>() { "Поле 1", "Поле 2", "Поле 3", "Поле 4" };
        }
    }

    public static ObservableCollection<string> ConditionType
    {
        get
        {
            return new ObservableCollection<string>() { ">", "<", "=" };
        }
    }
}

public class Condition : BaseModel
{
    private ObservableCollection<object> _ChildNodes;
    public ObservableCollection<object> ChildNodes
    {
        get { return _ChildNodes; }
        set { _ChildNodes = value; Notify("ChildNodes"); }
    }

    public string ConditionType { get; set; }
}

public class Field : BaseModel
{
    public ObservableCollection<string> Fields
    {
        get
        {
            return PickList.Fields;
        }
    }
    public ObservableCollection<string> ConditionTypes
    {
        get
        {
            return PickList.ConditionType;
        }
    }

    public string Name { get; set; }
    public string ConditionType { get; set; }
    public string Value { get; set; }
}

public class Button : BaseModel
{
    public string Name { get; set; }
}

Converter

    public sealed class DataTemplateSelector : IValueConverter
{

    public DataTemplate ConditionDataTemplate { get; set; }

    public DataTemplate FieldDataTemplate { get; set; }

    public DataTemplate ButtonDataTemplate { get; set; }

    public DataTemplate DefaultDataTemplate { get; set; }

    public DataTemplateSelector()
    {
    }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value != null)
        {
            Type type = value.GetType();


            if (typeof(Condition).TypeHandle == type.TypeHandle)
            {
                return ConditionDataTemplate;
            }
            else if (typeof(Field).TypeHandle == type.TypeHandle)
            {
                return FieldDataTemplate;
            }
            else if (typeof(Button).TypeHandle == type.TypeHandle)
            {
                return ButtonDataTemplate;
            }
        }

        return DefaultDataTemplate;
    }

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

Je prévois d'ajouter les types d'affichage des champs DateTime, Bool, ...

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top