WPF: Erro usando um controle personalizado no ItemTemplate de outro controle personalizado
-
22-09-2019 - |
Pergunta
Eu tenho uma biblioteca de controle personalizada, onde tenho vários controles personalizados que uso no meu aplicativo principal. Eu tenho um controle personalizado simples que permite que o usuário selecione valores de espessura da caneta de um ComboBox. Agora, estou criando um novo controle personalizado, com base em uma caixa de listagem, e quero incluir o ComboBoBox de espessura da caneta no novo ItemTemplate do novo controle personalizado.
Estou recebendo este erro:
"Não é possível criar a instância de" LinethicknessComboBox "definido nos montagens de montagem, a exceção foi lançada pelo alvo de uma invocação. Erro no objeto" 10_T "no arquivo de marcação 'CustomControls; component/temes/customlistbox.general.xaml'.
Aqui está o xaml e o código por trás do LinethicknessComboBox:
namespace CustomControls
{
public class LineThicknessComboBox : ComboBox
{
public LineThicknessComboBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(LineThicknessComboBox)
, new FrameworkPropertyMetadata(typeof(LineThicknessComboBox)));
}
}
}
e em linethicknesscombobox.generic.xaml:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CustomControls">
<Style TargetType="{x:Type local:LineThicknessComboBox}" BasedOn="{StaticResource {x:Type ComboBox}}">
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
...
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Aqui está o XAML e o CodeBehind para o meu novo Lista CustomListBox:
namespace CustomControls
{
public class CustomListBox : ListBox
{
public CustomListBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomListBox)
, new FrameworkPropertyMetadata(typeof(CustomListBox)));
}
}
}
e no customlistbox.generic.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CustomControls">
<Style TargetType="{x:Type local:CustomListBox}" BasedOn="{StaticResource {x:Type ListBox}}">
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<Border>
...
<local:LineThicknessComboBox />
...
</Border>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
E aqui está o meu generix.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="CustomControls;component/Themes/LineThicknessComboBox.Generic.xaml"/>
<ResourceDictionary Source="CustomControls;component/Themes/CustomListBox.Generic.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
Estou pensando que tenho algum tipo de problema de referência, mas não consigo descobrir o que está errado. O programa compila e é executado sem nenhum aviso/erros, mas quando o ListBox CustomList é criado no meu aplicativo principal, recebo o erro listado acima. Sem incluir o LinethicknessComboBox, o ListBox CustomList funciona bem.
Alguém pode explicar por que estou recebendo esse erro? É possível incluir meu controle personalizado em outro, mesmo que eles estejam na mesma biblioteca de controle personalizada, correto?
Obrigado!
Solução
// Acho que deve ser o construtor estático em ambos os casos, porque a substituição dos metadados da propriedade de dependência deve sempre ser feita no construtor estático.
// not public LineThicknessComboBox()
static LineThicknessComboBox()
{
DefaultStyleKeyProperty.OverrideMetadata(
typeof(LineThicknessComboBox)
, new FrameworkPropertyMetadata(
typeof(LineThicknessComboBox)));
}
Chamadas para Overidemetadata deve ser executado apenas dentro dos construtores estáticos do tipo que se fornece como o parâmetro do quinto e o método ou por meio de instanciação semelhante. Tentar alterar metadados após a existência de instâncias do tipo de proprietário não aumentará exceções, mas resultará em comportamentos inconsistentes no sistema de propriedades.
De msdn
Outras dicas
Você pode estar enfrentando um problema com o DesignMode e o código no seu construtor. Não posso dizer com certeza, pois tive meu quinhão de problemas com os controles do usuário do WPF e a superfície do design, e todos eles têm erros enigmáticos como este.
A solução é usar a classe System.ComponentModel.DesignerProperties para verificar se você está no modo de design e envolver qualquer código que não funcione no modo de design em um bloco IF para impedir que ele seja executado:
namespace CustomControls
{
public class LineThicknessComboBox : ComboBox
{
public LineThicknessComboBox()
{
// Design-mode capable code...
if (DesignerProperties.GetIsInDesignMode(this)) return;
// Design mode incapable code...
DefaultStyleKeyProperty.OverrideMetadata(typeof(LineThicknessComboBox)
, new FrameworkPropertyMetadata(typeof(LineThicknessComboBox)));
}
}
}