문제

Suppose in a xaml window I have <UserControl x:Name="Test">... I have a custom MyListBoxItem with only one dependencyproperty UserControlProperty added, typeof UserControl.

I want to use the syntax <c:MyListBoxItem UserControl="Test">Information</c:MyListBoxItem> and I am not sure how to write a typeconverter from the string "Test" or perhaps "local:Test" to the usercontrol Test on that xaml page.

In answer to a comment of 'nit':

<Window.Resources>
    <UserControl x:Key="Test" x:Name="Test"
                 x:Shared="False">
        <Button Height="50"
                Width="50" />
    </UserControl>
</Window.Resources>

with <c:MyListBoxItem UserControl="{StaticResource Test}">Information</c:MyListBoxItem> works. However I wanted the UserControl in the regular xaml definitions and found two other ways of doing it:

<c:MyListBoxItem UserControl="{x:Reference Test}">

However x:Reference gives a complie time error: method/operation not implemented. It still runs which btw is weird imo. And:

<c:MyListBoxItem UserControl="{Binding ElementName=Test}"

which is the good solution.

As for what you can achieve by this:

private void Menu_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
  foreach (var item in e.RemovedItems)
  {
    // collapse usercontrol
    UserControl uc = (item as MyListBoxItem).UserControl;
    if (uc != null) uc.Visibility = Visibility.Collapsed;
            }
  foreach (var item in e.AddedItems)
  {
     // uncollapse usercontrol
     UserControl uc = (item as MyListBoxItem).UserControl;
     if (uc != null) uc.Visibility = Visibility.Visible;
  }
}

This is a nice way to support this kind of menu structure and the xaml definition is also clarifying:

<c:MyListBoxItem UserControl="{Binding ElementName=Information}" IsSelected="True">Information</c:MyListBoxItem>
<c:MyListBoxItem UserControl="{Binding ElementName=Edit}" IsSelected="False">Edit</c:MyListBoxItem>

<Grid>
   <UserControl x:Name="Information" Visibility="Visible"><Button Content="Placeholder for usercontrol Information" /></UserControl>
   <UserControl x:Name="Edit" Visibility="Collapsed"> <Button Content="Placeholder for usercontrol Edit" /></UserControl>
도움이 되었습니까?

해결책

I am not sure what you want to achieve by doing this, but you will have to put that UserControl in the resources

<Window.Resources>
 <UserControl x:Key="Test" x:Shared="false">
</Window.Resources>

Then you can set your DP as

    <c:MyListBoxItem UserControl="{StaticResource Test}">Information</c:MyListBoxItem>

다른 팁

If you want to use an actual TypeConverter, you should be able to do something like this:

public class UserControlConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        if (sourceType == typeof(string)) return true;
        return base.CanConvertFrom(context, sourceType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        if (value is string)
        {
            Type userControlType = Type.GetType(value.ToString(), true, true);
            return Activator.CreateInstance(userControlType);
        }
        return base.ConvertFrom(context, culture, value);
    }

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
    {
        if (destinationType == typeof(UserControl))
        {
            return destinationType.FullName;
        }
        return base.ConvertTo(context, culture, value, destinationType);
    }
}

I haven't had a chance to test this, so please let me know if you have any problems. Also, please note that you will need to use the full name of the type, so something like this: ApplicationName.ProjectOrFolderNameIfApplicable.ControlName. Please also note that this will just call the default (empty) constructor of the UserControl.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top