Tengo un conjunto de controles con comandos y lógica adjuntos que se reutilizan constantemente de la misma manera. Decidí crear un control de usuario que contenga todos los controles y la lógica comunes.
Sin embargo, también necesito el control para poder contener contenido que pueda ser nombrado. Intenté lo siguiente:
<UserControl.ContentTemplate>
<DataTemplate>
<Button>a reused button</Button>
<ContentPresenter Content="{TemplateBinding Content}"/>
<Button>a reused button</Button>
</DataTemplate>
</UserControl.ContentTemplate>
Sin embargo, parece que no se puede nombrar ningún contenido colocado dentro del control de usuario. Por ejemplo, si uso el control de la siguiente manera:
<lib:UserControl1>
<Button Name="buttonName">content</Button>
</lib:UserControl1>
Recibo el siguiente error:
No se puede establecer el valor del atributo de nombre 'buttonName' en el elemento 'Button'. 'Botón' está bajo el alcance del elemento 'UserControl1', que ya tenía un nombre registrado cuando se definió en otro alcance.
Si elimino el buttonName, se compila, sin embargo, necesito poder nombrar el contenido. ¿Cómo puedo conseguir esto?
Respuestas:
La respuesta es no usar UserControl para hacerlo.
Cree una clase que amplíe ContentControl
luego usa un estilo para especificar el contenido
y finalmente - úsalo
fuente
UserControl
heredarContentControl
. Para resolverlo, simplemente agregue una nueva clase ( no XAML con CS). Y luego funcionará (con suerte). si lo desea, he creado una pequeña soluciónHeadingContainer
yMyFunkyContainer
están destinados a serMyFunkyControl
?Parece que esto no es posible cuando se usa XAML. Los controles personalizados parecen ser exagerados cuando en realidad tengo todos los controles que necesito, pero solo necesito agruparlos con un poco de lógica y permitir contenido con nombre.
La solución en el blog de JD, como sugiere mackenir, parece tener el mejor compromiso. Una forma de extender la solución de JD para permitir que los controles aún se definan en XAML podría ser la siguiente:
En mi ejemplo anterior, he creado un control de usuario llamado UserControlDefinedInXAML que se define como cualquier control de usuario normal que usa XAML. En mi UserControlDefinedInXAML tengo un StackPanel llamado aStackPanel dentro del cual quiero que aparezca mi contenido con nombre.
fuente
Otra alternativa que he usado es simplemente establecer la
Name
propiedad en elLoaded
evento.En mi caso, tenía un control bastante complejo que no quería crear en el código subyacente, y buscaba un control opcional con un nombre específico para cierto comportamiento, y como noté que podía establecer el nombre en un
DataTemplate
Pensé que también podría hacerlo en elLoaded
evento.fuente
A veces, es posible que solo necesite hacer referencia al elemento de C #. Dependiendo del caso de uso, puede establecer an en
x:Uid
lugar de anx:Name
y acceder a los elementos llamando a un método de búsqueda de Uid como Obtener objeto por su Uid en WPF .fuente
Puede utilizar este ayudante para establecer el nombre dentro del control de usuario:
y su ventana o código de control subyacente establece que controla por propiedad:
tu ventana xaml:
UserControlNameHelper obtiene su nombre de control y su nombre de clase para establecer Control en Propiedad.
fuente
Elegí crear una propiedad adicional para cada elemento que necesito obtener:
Esto me permite acceder a los elementos secundarios en XAML:
fuente
Código detrás:
La solución real sería que Microsoft solucionara este problema, así como todos los demás con árboles visuales rotos, etc. Hipotéticamente hablando.
fuente
Otra solución alternativa: haga referencia al elemento como RelativeSource .
fuente
Tuve el mismo problema al usar un TabControl al colocar un montón de controles con nombre en.
Mi solución fue usar una plantilla de control que contiene todos mis controles para que se muestren en una página de pestañas. Dentro de la plantilla, puede usar la propiedad Name y también enlazar datos a propiedades del control nombrado desde otros controles al menos dentro de la misma plantilla.
Como Contenido del Control TabItem, use un Control simple y configure ControlTemplate en consecuencia:
Para acceder a los controles nombrados dentro de la plantilla desde el código detrás, necesitaría usar el árbol visual.
fuente