Eu tenho um conjunto de controles com comandos e lógica anexados que são constantemente reutilizados da mesma maneira. Decidi criar um controle de usuário que contenha todos os controles e lógicas comuns.
No entanto, também preciso do controle para poder conter o conteúdo que pode ser nomeado. Tentei o seguinte:
<UserControl.ContentTemplate>
<DataTemplate>
<Button>a reused button</Button>
<ContentPresenter Content="{TemplateBinding Content}"/>
<Button>a reused button</Button>
</DataTemplate>
</UserControl.ContentTemplate>
No entanto, parece que qualquer conteúdo colocado dentro do controle do usuário não pode ser nomeado. Por exemplo, se eu usar o controle da seguinte maneira:
<lib:UserControl1>
<Button Name="buttonName">content</Button>
</lib:UserControl1>
Recebo o seguinte erro:
Não é possível definir o valor do atributo Name 'buttonName' no elemento 'Button'. 'Botão' está no escopo do elemento 'UserControl1', que já tinha um nome registrado quando foi definido em outro escopo.
Se eu remover o buttonName, ele será compilado, mas preciso nomear o conteúdo. Como posso conseguir isso?
Respostas:
A resposta é não usar um UserControl para fazer isso.
Crie uma classe que estenda ContentControl
então use um estilo para especificar o conteúdo
e finalmente - use-o
fonte
UserControl
para herdarContentControl
. Para resolver, basta adicionar uma nova classe ( não XAML com CS). E então (espero) funcionará. se quiser, criei uma pequena solução VS2010HeadingContainer
eMyFunkyContainer
é para serMyFunkyControl
?!Parece que isso não é possível quando o XAML é usado. Os controles personalizados parecem ser um exagero quando, na verdade, tenho todos os controles de que preciso, mas só preciso agrupá-los com um pouco de lógica e permitir conteúdo nomeado.
A solução no blog de JD, como sugere mackenir, parece ter o melhor compromisso. Uma maneira de estender a solução JD para permitir que os controles ainda sejam definidos em XAML pode ser a seguinte:
No meu exemplo acima, criei um controle de usuário denominado UserControlDefinedInXAML, que é definido como qualquer controle de usuário normal usando XAML. Em meu UserControlDefinedInXAML, tenho um StackPanel chamado aStackPanel no qual desejo que meu conteúdo nomeado apareça.
fonte
Outra alternativa que usei é apenas definir a
Name
propriedade noLoaded
evento.No meu caso, eu tinha um controle bastante complexo que não queria criar no code-behind, e ele procurou um controle opcional com um nome específico para determinado comportamento, e desde que percebi que poderia definir o nome em um
DataTemplate
Achei que poderia fazer isso noLoaded
evento também.fonte
Às vezes, você só precisa fazer referência ao elemento do C #. Dependendo do caso de uso, você pode definir um em
x:Uid
vez de umx:Name
e acessar os elementos chamando um método localizador de Uid como Get object por seu Uid no WPF .fonte
Você pode usar este auxiliar para definir o nome dentro do controle do usuário:
e sua janela ou código de controle atrás definido, você controla por propriedade:
sua janela xaml:
UserControlNameHelper obtém seu nome de controle e seu nome de classe para definir Control como Property.
fonte
Decidi criar uma propriedade extra para cada elemento que preciso obter:
Isso me permite acessar os elementos filho em XAML:
fonte
Código por trás:
A solução real seria a Microsoft corrigir esse problema, bem como todos os outros com árvores visuais quebradas, etc. Hipoteticamente falando.
fonte
Ainda outra solução alternativa: referencie o elemento como RelativeSource .
fonte
Eu tive o mesmo problema ao usar um TabControl ao colocar um monte de controles nomeados em.
Minha solução alternativa foi usar um modelo de controle que contém todos os meus controles para serem mostrados em uma página de guia. Dentro do modelo, você pode usar a propriedade Name e também vincular dados às propriedades do controle nomeado de outros controles, pelo menos dentro do mesmo modelo.
Como conteúdo do controle TabItem, use um controle simples e defina o ControlTemplate de acordo:
Para acessar esses controles nomeados dentro do modelo a partir do código por trás, você precisará usar a árvore visual.
fonte