Dado que no hay una respuesta samilar, he puesto mi solución aquí:
public class RadioMenuItem : MenuItem
{
public string GroupName { get; set; }
protected override void OnClick()
{
var ic = Parent as ItemsControl;
if (null != ic)
{
var rmi = ic.Items.OfType<RadioMenuItem>().FirstOrDefault(i =>
i.GroupName == GroupName && i.IsChecked);
if (null != rmi) rmi.IsChecked = false;
IsChecked = true;
}
base.OnClick();
}
}
En XAML solo Úselo como un elemento de menú habitual:
<MenuItem Header="OOO">
<local:RadioMenuItem Header="111" GroupName="G1"/>
<local:RadioMenuItem Header="222" GroupName="G1"/>
<local:RadioMenuItem Header="333" GroupName="G1"/>
<local:RadioMenuItem Header="444" GroupName="G1"/>
<local:RadioMenuItem Header="555" GroupName="G1"/>
<local:RadioMenuItem Header="666" GroupName="G1"/>
<Separator/>
<local:RadioMenuItem Header="111" GroupName="G2"/>
<local:RadioMenuItem Header="222" GroupName="G2"/>
<local:RadioMenuItem Header="333" GroupName="G2"/>
<local:RadioMenuItem Header="444" GroupName="G2"/>
<local:RadioMenuItem Header="555" GroupName="G2"/>
<local:RadioMenuItem Header="666" GroupName="G2"/>
</MenuItem>
Bastante simple y limpio. Y, por supuesto, puede hacer que el GroupName
sea una propiedad de dependencia mediante algunos códigos adicionales, eso es lo mismo que otros.
Por cierto, si no te gusta la marca de verificación, puede cambiarlo a lo que le gusta:
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
var p = GetTemplateChild("Glyph") as Path;
if (null == p) return;
var x = p.Width/2;
var y = p.Height/2;
var r = Math.Min(x, y) - 1;
var e = new EllipseGeometry(new Point(x,y), r, r);
// this is just a flattened dot, of course you can draw
// something else, e.g. a star? ;)
p.Data = e.GetFlattenedPathGeometry();
}
Si ha utilizado un montón de este RadioMenuItem
en su programa, hay otra versión más eficiente se muestra a continuación . Los datos literales se obtienen de e.GetFlattenedPathGeometry().ToString()
en el fragmento de código anterior.
private static readonly Geometry RadioDot = Geometry.Parse("M9,5.5L8.7,7.1 7.8,8.3 6.6,9.2L5,9.5L3.4,9.2 2.2,8.3 1.3,7.1L1,5.5L1.3,3.9 2.2,2.7 3.4,1.8L5,1.5L6.6,1.8 7.8,2.7 8.7,3.9L9,5.5z");
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
var p = GetTemplateChild("Glyph") as Path;
if (null == p) return;
p.Data = RadioDot;
}
Y por último, si va a envolver para su uso en el proyecto, se debe ocultar IsCheckable
propiedad de la clase base, ya que el machenism comprobación automática de MenuItem
clase dirigirá el estado de comprobación de radio marca un mal comportamiento.
private new bool IsCheckable { get; }
De este modo VS dará un error si un novato intenta compilar XAML como esto:
// en cuenta que este es un uso incorrecto!
<local:RadioMenuItem Header="111" GroupName="G1" IsCheckable="True"/>
// en cuenta que este es un uso incorrecto!
En base a las respuestas proporcionadas, Diría que no hay una manera más fácil de hacerlo en el código subyacente con un bucle foreach que desmarca todos los elementos además del elemento nuevamente marcado. –