我是WPF的新手,想在StackPanel中创建一个包含三个RadioBox的UserControl。每个单选按钮都有一个IsChecked属性。我希望通过发布指示当前选择的整数属性来简化对该选择的访问,将其称为SelectedIndex。
因此,当检查第一个无线电时,我的用户控制的SelectedIndex值应为0;当选中第二个无线电时,SelectedIndex应为1,依此类推。这应该可以在任何一个方向上工作:当用户点击单选框时,SelectedIndex值应相应地改变。当通过代码或甚至某些数据绑定更改SelectedIndex值时,UI控件将相应地更新。
如何使用XAML代码执行此操作?我现在有以下代码:
public partial class CommandControl : UserControl
{
public static readonly DependencyProperty SelectedIndexProperty =
DependencyProperty.Register("SelectedIndex", typeof(int), typeof(CommandControl));
public int SelectedIndex
{
get
{
return (int) GetValue(SelectedIndexProperty);
}
set
{
SetValue(SelectedIndexProperty, value);
}
}
public CommandControl()
{
InitializeComponent();
}
}
XAML部分:
<UserControl x:Class="MyNamespace.CommandControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="65" d:DesignWidth="219"
x:Name="me">
<StackPanel HorizontalAlignment="Left" Name="stackPanel1" VerticalAlignment="Center" Orientation="Horizontal">
<RadioButton Content="Disable" Name="disableRadio" VerticalAlignment="Center" IsChecked="True" />
<RadioButton Content="Enable" Name="enableRadio" VerticalAlignment="Center" Margin="5,0,0,0" />
<RadioButton Content="Configure" Name="configureRadio" VerticalAlignment="Center" Margin="5,0,0,0" />
</StackPanel>
</UserControl>
我知道如何从UserControl的属性传递值(例如RadioButton的Text之一)。但这一次,我需要将“外部”int值映射到三个“内部”bool值,当数字具有特定值时,每个值都为true。我想这应该直接在XAML中完成,但我无法弄清楚如何实现这一点。
或者为该转换编写C#代码会更好吗?我现在可能会这样做,但我仍然不确定特殊的DependencyProperty代码,我想,它可能会在不通过我的setter的情况下更改其值。
答案 0 :(得分:0)
只使用布尔strait up而不是integer = 0或integer = 1.公开一个Public Boolean属性,例如rbDisbleIsChecked并将IsChecked绑定到该属性。如果你真的想将Integer用于公共属性,那么你将需要使用转换器,因为IsChecked是布尔值。
如果希望Integer表示当前选定的当前值,则可以在布尔公共属性的集合中设置该值。
或者你无法绑定,只是连接到相同或单独的已检查事件。在事件中设置SelectedIndex。如果你将它们连接到同一个事件,那么你需要命名它们,因此事件调用确定检查了哪个。
答案 1 :(得分:0)
最常见的解决方案是不要尝试使用选择了RadioButton
的数字表示,因为如果你尝试的话,你会反对这个流程。
然而,尝试回答这个问题......
我认为我不会尝试在XAML中解决这个问题,因为这不符合XAML的优势。 WPF相对较新的人通常会尝试在XAML中尽一切可能,无论它是否有意义,因为他们从某个地方获得了你应该做的事情。
我不是说这是不可能的。以免你认为我试图说服你,因为我不知道如何在XAML中做到这一点,我会准确地说明我认为你不应该这样做。这适用于“作品”的小值:
<UserControl
x:Class="MyNamespace.CommandControl"
xmlns:loc="clr-namespace:MyNamespace"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="65" d:DesignWidth="219"
x:Name="me">
<StackPanel HorizontalAlignment="Left" Name="stackPanel1" VerticalAlignment="Center" Orientation="Horizontal">
<RadioButton Content="Disable" Name="disableRadio" VerticalAlignment="Center" IsChecked="True" />
<RadioButton Content="Enable" Name="enableRadio" VerticalAlignment="Center" Margin="5,0,0,0" />
<RadioButton Content="Configure" Name="configureRadio" VerticalAlignment="Center" Margin="5,0,0,0" />
</StackPanel>
<UserControl.Style>
<Style TargetType="loc:MyNamespace">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=disableRadio, Path=IsChecked}" Value="True">
<DataTrigger.Setters>
<Setter Property="SelectedIndex" Value="0" />
</DataTrigger.Setters>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=enableRadio, Path=IsChecked}" Value="True">
<DataTrigger.Setters>
<Setter Property="SelectedIndex" Value="1" />
</DataTrigger.Setters>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=configureRadio, Path=IsChecked}" Value="True">
<DataTrigger.Setters>
<Setter Property="SelectedIndex" Value="2" />
</DataTrigger.Setters>
</DataTrigger>
</Style.Triggers>
</Style>
</UserControl.Style>
</UserControl>
但这非常狡猾。首先,Visual Studio将假装出现错误 - 只要您打开此Xaml文件,它就会报告错误“'CommandControl'TargetType与元素类型'UserControl'不匹配。”其次,只有将Style
放在用户控件的主体后面才有效。坦率地说,这些问题都是代码味道 - 这可能是你可能做错事的线索。在这种情况下,你会是。
顺便说一句,Visaul Studio没有用错误信息说出真相 - 这不是编译时错误,程序将构建并运行,并使用以下主窗口内容:
<Grid>
<my:CommandControl HorizontalAlignment="Left" Margin="224,114,0,0" x:Name="commandControl1" VerticalAlignment="Top" />
<TextBlock Height="82" HorizontalAlignment="Left" Margin="76,162,0,0" Name="textBlock1" Text="{Binding ElementName=commandControl1, Path=SelectedIndex}" VerticalAlignment="Top" Width="237" />
</Grid>
我已经确认这会正确更新该属性。
但这都错了。
首先,您在这里尝试创建的是编程功能 - 您正在确定控件的API行为方式。这远远超出了XAML的优势。哎呀,即使在XAML中嵌入交互行为也是值得怀疑的。我的观点是XAML主要用于应用程序的布局和外观。
所以代码隐藏真的是你正在做的事情的地方。只需使用良好的老式事件处理。请务必使用SetCurrentValue
更新您的depenedency属性的值。不要只使用setter,因为这会破坏你的属性的任何数据绑定或其他DP特定用途,并且基本上会破坏使它成为DP的重点。
此外,我不会将其称为SelectedIndex
,因为这是一个属性名称,通常意味着WPF中的特定内容 - 它主要由支持选择的ItemsControl派生控件使用。那不是你在这里所做的,所以我倾向于选择一个通常没有意义的名字。除非我已经说过,我认为在任何情况下我都不会使用数字索引。
答案 2 :(得分:0)
使用这样的值转换器:
public class RadioValueConverter : IValueConverter
{
public int Value { get; set; }
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if ((int)value == Value)
{
return true;
}
return false;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if ((bool)value == true)
{
return Value;
}
return null;
}
}
在ConvertBack中,单击RadioButton将始终设置一个true值,因此您永远不应该返回null。我不知道至少会发生这种情况。
然后在您的XAML中,您可以为每个RadioButton创建一个转换器:
<StackPanel HorizontalAlignment="Left" Name="stackPanel1" VerticalAlignment="Center" Orientation="Horizontal">
<StackPanel.Resources>
<loc:RadioValueConverter x:Key="FirstValue" Value="1"/>
<loc:RadioValueConverter x:Key="SecondValue" Value="2"/>
<loc:RadioValueConverter x:Key="ThirdValue" Value="3"/>
</StackPanel.Resources>
<RadioButton Content="Disable" Name="disableRadio" VerticalAlignment="Center" IsChecked="{Binding SelectedIndex, Converter={StaticResource FirstValue}}" />
<RadioButton Content="Enable" Name="enableRadio" VerticalAlignment="Center" Margin="5,0,0,0" IsChecked="{Binding SelectedIndex, Converter={StaticResource SecondValue}}" />
<RadioButton Content="Configure" Name="configureRadio" VerticalAlignment="Center" Margin="5,0,0,0" IsChecked="{Binding SelectedIndex, Converter={StaticResource ThirdValue}}"/>
</StackPanel>
这也应该提供双向绑定,所以如果你在其他地方更改SelectedIndex,RadioButtons将会跟随。
另外,我之前忘了提到但是这段代码假设你已经将CommandControl的DataContext设置为自身,即在构造函数中:
public CommandControl()
{
InitializeComponent();
DataContext = this;
SelectedIndex = 1;
}