开发者

C# Generic User Control WPF

I've trying to build a user cont开发者_如何学编程rol that will display the content of a Dictionary

the problem is i don't know the types for the key and value in the User control, i would know at the point i create the user control but C# doesn't seem to want to let me create a Generic User Control that would let me pass them in to a hosted dictionary

ie

public class MyCtrl<TKey,TValue> : UserControl
{
    private Dictionary<TKey,TValue>
}

because it references a generated file in the .\Obj\Debug\MyCtrl.g.i.cs which is read only

the only solution that is presenting itself to me is to create the class from scratch and not letting the designer handle any of the formatting is there a better possiblity?

to give a little background in about 8-10 places in my code i need the user to populate dictionaries of values and instead of building 8-10 controls that all do exactly the same thing but with different Types (in fact a lot of the time the only difference is which enum is serving as the key) i wanted a single control to handle this


You can use generic as if you don’t use XAML. But if you want to use XAML to define your control, you can’t use generic


I finally have a working answer.

I build the Control around a Hashtable that uses objects

then add an extension to the object class

    public static bool TryParse<TType>(this object obj, out TType result) 
    {
        try
        {
            result = (TType)Convert.ChangeType(obj, typeof(TType));
            return true;
        }
        catch
        {
            result = default(TType);
            return false;
        }
    }
    public static TType Parse<TType>(this object obj) where TType : struct
    {
        try
        {
            return (TType)Convert.ChangeType(obj, typeof(TType));
        }
        catch
        {
            throw new InvalidCastException("Cant cast object to " + typeof(TType).Name);
        }
    }

then add a generic property that calls the extension to cast the objects to a Dictionary


If you want to be able to use your control in xaml you wont be able to create a generic UserControl in this way as WPF just doesn't support it. How would you declaratively instantiate that type in xaml?

I'd look at how other controls would handle something like this. For instance a ListBox allows you to populate a list of items without any regard to the type of collection parsed into its ItemsSource.

<ListBox ItemsSource="{Binding DictionaryItems}" >
   <ListBox.ItemTemplate>
      <DataTemplate>
         <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding Key}" />
            <TextBlock Text="{Binding Value}" />
         </StackPanel>
      </DataTemplate>
   </ListBox.ItemTemplate>
 </ListBox>

For your various dictionary types you could then have multiple DataTemplates for each different dictionary type and switch using a TemplateSelector.

public class SomeSelector : DataTemplateSelector
{
   public DataTemplate Template1 { get; set; }
   public DataTemplate Template2 { get; set; }

   public override DataTemplate SelectTemplate(object item, DependencyObject container)
   {
      if (item is IDictionary<string, int>) 
      {
         return Template1;
      }

      return Template2;
   }
}

Then in xaml

<UserControl.Resources>
   <DataTemplate x:Key="Template1">
      <StackPanel Orientation="Horizontal">
         <TextBlock Text="{Binding Key}" />
         <TextBlock Text="{Binding Value}" />
      </StackPanel>
   </DataTemplate>

   <DataTemplate x:Key="Template2>
      <StackPanel Orientation="Vertical">
         <TextBlock Text="{Binding Key}" />
         <TextBlock Text="{Binding Value}" />
      </StackPanel>
   </DataTemplate>

   <SomeSelector x:Key="SomeSelector" Template1="{StaticResource Template1}" Template2="{StaticResource Template2}" />
</UserControl.Resources>

<ListBox ItemsSource="{Binding DictionaryItems}" ItemTemplateSelector="{StaticResource SomeSelector}" />


You might be better off using MVVM, and putting all the generic types and constraints on your viewmodel, not your view.


As Steyca mentioned, you can't use generics in XAML. You can however create your generic user control, and derive specific types from this generic class, which you can use in XAML. This at least reduces code duplication to some extent.

As a sidenote, generics in XAML might be possible if you support it yourself, by passing the Type as the value of a property. At least, I believe that's the intent of this article, but I didn't have time yet to try it out myself.


The reason why you want to set a generic user control is because you dont know what the key and value in:

 private Dictionary<TKey,TValue> someDictionary;

types are going to be in advance I believe. If that is the case then declare your Dictionary as:

private Dictionary<dynamic,dynamic> someDictionary

then you will be able to add any type key and value to it. so make sure that if you key is an int and your values a string for instance then always follow that pattern. For example the compiler will let you compile this code:

        Dictionary<dynamic, dynamic> myDictionAry = new Dictionary<dynamic, dynamic>();
        myDictionAry.Add(1, "kd");
        myDictionAry.Add("kjdf", 3);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜