간단한 WPF 라디오 버튼 바인딩?
3개의 라디오 버튼 그룹을 값 1, 2 또는 3에 대한 유형 int 속성에 바인딩하는 가장 간단한 방법은 무엇입니까?
저는 간단한 해결책을 생각해냈습니다.
저는 다음과 함께 model.cs 클래스를 수강하고 있습니다.
private int _isSuccess;
public int IsSuccess { get { return _isSuccess; } set { _isSuccess = value; } }
DataContext가 model.cs 으로 설정된 Window1.xaml.cs 파일을 가지고 있습니다.xaml에는 라디오 버튼이 포함되어 있습니다.
<RadioButton IsChecked="{Binding Path=IsSuccess, Converter={StaticResource radioBoolToIntConverter}, ConverterParameter=1}" Content="one" />
<RadioButton IsChecked="{Binding Path=IsSuccess, Converter={StaticResource radioBoolToIntConverter}, ConverterParameter=2}" Content="two" />
<RadioButton IsChecked="{Binding Path=IsSuccess, Converter={StaticResource radioBoolToIntConverter}, ConverterParameter=3}" Content="three" />
변환기는 다음과 같습니다.
public class RadioBoolToIntConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
int integer = (int)value;
if (integer==int.Parse(parameter.ToString()))
return true;
else
return false;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return parameter;
}
}
물론 Window1의 리소스에는 다음과 같은 기능이 있습니다.
<Window.Resources>
<local:RadioBoolToIntConverter x:Key="radioBoolToIntConverter" />
</Window.Resources>
저는 아무도 이런 종류의 해결책을 생각해내지 못했다는 것에 놀랐습니다.가장 깨끗하지는 않지만 매우 쉽게 사용할 수 있습니다.
private bool[] _modeArray = new bool[] { true, false, false};
public bool[] ModeArray
{
get { return _modeArray ; }
}
public int SelectedMode
{
get { return Array.IndexOf(_modeArray, true); }
}
XAML 단위:
<RadioButton GroupName="Mode" IsChecked="{Binding Path=ModeArray[0], Mode=TwoWay}"/>
<RadioButton GroupName="Mode" IsChecked="{Binding Path=ModeArray[1], Mode=TwoWay}"/>
<RadioButton GroupName="Mode" IsChecked="{Binding Path=ModeArray[2], Mode=TwoWay}"/>
참고: 기본적으로 양방향 바인딩을 선택하지 않으려면 양방향 바인딩이 필요하지 않습니다.양방향 바인딩은 이 솔루션의 가장 큰 단점입니다.
찬성:
- 코드 뒤에 필요 없음
- 별도의 클래스가 필요하지 않음(IValue Converter)
- 추가 열거형이 필요하지 않음
- 이상한 바인딩이 필요하지 않습니다.
- 직설적이고 이해하기 쉬운
- MVVM을 위반하지 않습니다(헤, 적어도 그러길 바랍니다).
사실 컨버터를 그렇게 사용하면 양방향 바인딩이 깨지고, 위에서 말씀드린 것처럼 열거형에도 사용할 수 없습니다.이를 위한 더 나은 방법은 다음과 같은 ListBox에 대한 단순한 스타일을 사용하는 것입니다.
참고: DrWPF.com 의 예와 달리, 컨텐츠 발표자를 라디오 단추 안에 넣지 마십시오. 그렇지 않으면 버튼이나 다른 내용이 포함된 항목을 추가하면 포커스를 설정하거나 상호 작용할 수 없습니다.이 기술로 해결할 수 있습니다.또한 텍스트의 회색 처리와 레이블의 여백 제거를 처리해야 합니다. 그렇지 않으면 올바르게 렌더링되지 않습니다.이 스타일은 두 가지 모두를 처리합니다.
<Style x:Key="RadioButtonListItem" TargetType="{x:Type ListBoxItem}" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<DockPanel LastChildFill="True" Background="{TemplateBinding Background}" HorizontalAlignment="Stretch" VerticalAlignment="Center" >
<RadioButton IsChecked="{TemplateBinding IsSelected}" Focusable="False" IsHitTestVisible="False" VerticalAlignment="Center" Margin="0,0,4,0" />
<ContentPresenter
Content = "{TemplateBinding ContentControl.Content}"
ContentTemplate = "{TemplateBinding ContentControl.ContentTemplate}"
ContentStringFormat = "{TemplateBinding ContentControl.ContentStringFormat}"
HorizontalAlignment = "{TemplateBinding Control.HorizontalContentAlignment}"
VerticalAlignment = "{TemplateBinding Control.VerticalContentAlignment}"
SnapsToDevicePixels = "{TemplateBinding UIElement.SnapsToDevicePixels}" />
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="RadioButtonList" TargetType="ListBox">
<Style.Resources>
<Style TargetType="Label">
<Setter Property="Padding" Value="0" />
</Style>
</Style.Resources>
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="ItemContainerStyle" Value="{StaticResource RadioButtonListItem}" />
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBox}">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="TextBlock.Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="HorizontalRadioButtonList" BasedOn="{StaticResource RadioButtonList}" TargetType="ListBox">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel Background="Transparent" Orientation="Horizontal" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
이제 라디오 버튼의 모양과 느낌을 확인할 수 있지만 양방향 바인딩과 열거형을 사용할 수 있습니다.어떻게...
<ListBox Style="{StaticResource RadioButtonList}"
SelectedValue="{Binding SomeVal}"
SelectedValuePath="Tag">
<ListBoxItem Tag="{x:Static l:MyEnum.SomeOption}" >Some option</ListBoxItem>
<ListBoxItem Tag="{x:Static l:MyEnum.SomeOtherOption}">Some other option</ListBoxItem>
<ListBoxItem Tag="{x:Static l:MyEnum.YetAnother}" >Yet another option</ListBoxItem>
</ListBox>
또한 ListBoxItem을 인라인으로 배치하는 대신 추적하는 스타일을 명시적으로 구분했기 때문에 다른 예제에서 보여주었듯이 이제 새로운 스타일을 생성하여 간격과 같은 항목별로 사용자 지정할 수 있습니다.(키가 지정된 스타일이 일반 제어 대상을 재정의하므로 ListBoxItem을 대상으로 지정하려는 경우에는 이 작업이 수행되지 않습니다.)
다음은 각 항목의 위와 아래에 6의 여백을 두는 예입니다.(위에서 언급한 이유로 ListBox의 리소스 섹션에서 ListBoxItem을 대상으로 하지 않고 ItemContainerStyle 속성을 통해 스타일을 명시적으로 적용해야 하는 방법에 주목하십시오.)
<Window.Resources>
<Style x:Key="SpacedRadioButtonListItem" TargetType="ListBoxItem" BasedOn="{StaticResource RadioButtonListItem}">
<Setter Property="Margin" Value="0,6" />
</Style>
</Window.Resources>
<ListBox Style="{StaticResource RadioButtonList}"
ItemContainerStyle="{StaticResource SpacedRadioButtonListItem}"
SelectedValue="{Binding SomeVal}"
SelectedValuePath="Tag">
<ListBoxItem Tag="{x:Static l:MyEnum.SomeOption}" >Some option</ListBoxItem>
<ListBoxItem Tag="{x:Static l:MyEnum.SomeOtherOption}">Some other option</ListBoxItem>
<ListBoxItem Tag="{x:Static l:MyEnum.YetAnother}" >Ter another option</ListBoxItem>
</ListBox>
너무 늦었다는 것은 알지만, 더 가볍고 간단한 대안이 있습니다. 에서 클래스System.Windows.Controls.RadioButton
두 가지 합니다.RadioValue
그리고.RadioBinding
그런 다음 클래스 코드에서 재정의합니다.OnChecked
설합니다를 합니다.RadioBinding
치에 재가치산의 .RadioValue
트랩이 바뀝니다.RadioBinding
및새이 콜을사는의 RadioValue
성, 설을 합니다.IsChecked
의 true
.
코드는 다음과 같습니다.
public class MyRadioButton : RadioButton
{
public object RadioValue
{
get { return (object)GetValue(RadioValueProperty); }
set { SetValue(RadioValueProperty, value); }
}
// Using a DependencyProperty as the backing store for RadioValue.
This enables animation, styling, binding, etc...
public static readonly DependencyProperty RadioValueProperty =
DependencyProperty.Register(
"RadioValue",
typeof(object),
typeof(MyRadioButton),
new UIPropertyMetadata(null));
public object RadioBinding
{
get { return (object)GetValue(RadioBindingProperty); }
set { SetValue(RadioBindingProperty, value); }
}
// Using a DependencyProperty as the backing store for RadioBinding.
This enables animation, styling, binding, etc...
public static readonly DependencyProperty RadioBindingProperty =
DependencyProperty.Register(
"RadioBinding",
typeof(object),
typeof(MyRadioButton),
new FrameworkPropertyMetadata(
null,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
OnRadioBindingChanged));
private static void OnRadioBindingChanged(
DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
MyRadioButton rb = (MyRadioButton)d;
if (rb.RadioValue.Equals(e.NewValue))
rb.SetCurrentValue(RadioButton.IsCheckedProperty, true);
}
protected override void OnChecked(RoutedEventArgs e)
{
base.OnChecked(e);
SetCurrentValue(RadioBindingProperty, RadioValue);
}
}
XAML 사용:
<my:MyRadioButton GroupName="grp1" Content="Value 1"
RadioValue="val1" RadioBinding="{Binding SelectedValue}"/>
<my:MyRadioButton GroupName="grp1" Content="Value 2"
RadioValue="val2" RadioBinding="{Binding SelectedValue}"/>
<my:MyRadioButton GroupName="grp1" Content="Value 3"
RadioValue="val3" RadioBinding="{Binding SelectedValue}"/>
<my:MyRadioButton GroupName="grp1" Content="Value 4"
RadioValue="val4" RadioBinding="{Binding SelectedValue}"/>
누군가가 이 모든 시간 후에 이것을 유용하게 찾기를 바랍니다 :)
다음을 사용하여 해결책을 생각해 냈습니다.Binding.DoNothing
양방향 바인딩이 깨지지 않는 컨버터에서 반환되었습니다.
public class EnumToCheckedConverter : IValueConverter
{
public Type Type { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null && value.GetType() == Type)
{
try
{
var parameterFlag = Enum.Parse(Type, parameter as string);
if (Equals(parameterFlag, value))
{
return true;
}
}
catch (ArgumentNullException)
{
return false;
}
catch (ArgumentException)
{
throw new NotSupportedException();
}
return false;
}
else if (value == null)
{
return false;
}
throw new NotSupportedException();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null && value is bool check)
{
if (check)
{
try
{
return Enum.Parse(Type, parameter as string);
}
catch(ArgumentNullException)
{
return Binding.DoNothing;
}
catch(ArgumentException)
{
return Binding.DoNothing;
}
}
return Binding.DoNothing;
}
throw new NotSupportedException();
}
}
용도:
<converters:EnumToCheckedConverter x:Key="SourceConverter" Type="{x:Type monitor:VariableValueSource}" />
라디오 버튼 바인딩:
<RadioButton GroupName="ValueSource"
IsChecked="{Binding Source, Converter={StaticResource SourceConverter}, ConverterParameter=Function}">Function</RadioButton>
이 예는 다소 길어 보일 수 있지만 그 의도는 상당히 분명해야 합니다.
부울 뷰모가다 3음지사를 합니다.FlagForValue1
,FlagForValue2
그리고.FlagForValue3
이 세 가지 속성은 각각 다음과 같은 단일 개인 필드에 의해 지원됩니다._intValue
.
보기(xaml)의 3개 Radio 버튼은 보기 모델에서 각각 해당하는 Flag 속성에 바인딩됩니다.은 " 1하는 라디오 이 "value 1"에 되어 있다는 것을 합니다.FlagForValue1
뷰 모델의 bool 속성과 그에 따라 다른 두 개의 속성이 표시됩니다.
모델에서 중 때 뷰에서속중예하설나정경는우하를성델모예경(:우▁when▁(▁one는▁setting하정설ties▁model▁in▁the▁view▁ofe:FlagForValue1
), 두 )에 FlagForValue2
,그리고.FlagForValue3
)는 UI(WPF)입니다.INotifyPropertyChanged
각 라디오 버튼을 올바르게 선택/선택 취소할 수 있습니다.
private int _intValue;
public bool FlagForValue1
{
get
{
return (_intValue == 1) ? true : false;
}
set
{
_intValue = 1;
RaisePropertyChanged("FlagForValue1");
RaisePropertyChanged("FlagForValue2");
RaisePropertyChanged("FlagForValue3");
}
}
public bool FlagForValue2
{
get
{
return (_intValue == 2) ? true : false;
}
set
{
_intValue = 2;
RaisePropertyChanged("FlagForValue1");
RaisePropertyChanged("FlagForValue2");
RaisePropertyChanged("FlagForValue3");
}
}
public bool FlagForValue3
{
get
{
return (_intValue == 3) ? true : false;
}
set
{
_intValue = 3;
RaisePropertyChanged("FlagForValue1");
RaisePropertyChanged("FlagForValue2");
RaisePropertyChanged("FlagForValue3");
}
}
샘플은 다음과 같습니다.
<RadioButton GroupName="Search" IsChecked="{Binding Path=FlagForValue1, Mode=TwoWay}"
>Value 1</RadioButton>
<RadioButton GroupName="Search" IsChecked="{Binding Path=FlagForValue2, Mode=TwoWay}"
>Value 2</RadioButton>
<RadioButton GroupName="Search" IsChecked="{Binding Path=FlagForValue3, Mode=TwoWay}"
>Value 3</RadioButton>
때때로 모델에서 다음과 같은 문제를 해결할 수 있습니다.옵션 A, 옵션 B, 옵션 C의 부울 속성이 3개 있다고 가정합니다.
XAML:
<RadioButton IsChecked="{Binding OptionA}"/>
<RadioButton IsChecked="{Binding OptionB}"/>
<RadioButton IsChecked="{Binding OptionC}"/>
코드:
private bool _optionA;
public bool OptionA
{
get { return _optionA; }
set
{
_optionA = value;
if( _optionA )
{
this.OptionB= false;
this.OptionC = false;
}
}
}
private bool _optionB;
public bool OptionB
{
get { return _optionB; }
set
{
_optionB = value;
if( _optionB )
{
this.OptionA= false;
this.OptionC = false;
}
}
}
private bool _optionC;
public bool OptionC
{
get { return _optionC; }
set
{
_optionC = value;
if( _optionC )
{
this.OptionA= false;
this.OptionB = false;
}
}
}
당신은 이해합니다.가장 깨끗한 것은 아니지만, 쉬운 것입니다.
Aviad P.의 답변은 매우 효과적입니다.그러나 OnRadioBindingChanged의 문자열을 비교하기 위해 equality 검사를 변경해야 했습니다. 그렇지 않으면 열거값이 문자열 값과 비교되고 처음에는 라디오 버튼이 선택되지 않았습니다.
private static void OnRadioBindingChanged(
DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
BindableRadioButton rb = (BindableRadioButton) d;
if (rb.RadioValue.Equals(e.NewValue?.ToString()))
{
rb.SetCurrentValue(IsCheckedProperty, true);
}
}
답변 2.0
위의 답변을 제공했지만 재구상된 것은 매우 강력합니다.ListBox
그것은 여전히 단순한 라디오 버튼에 이상적인 것과는 거리가 멉니다.이와 같이, 저는 훨씬 더 간단한 해결책을 생각해냈습니다. 대신에MarkupExtension
구하는하클스를 하는 하위 IValueConverter
그리고 그것은 의 힘으로 무장되어 있습니다.Binding.DoNothing
양방향 바인딩을 작동시키는 마법의 소스
스칼라 값에 바인딩
스칼라에 결합하는 컨버터 자체를 살펴봅시다.
public class RadioButtonConverter : MarkupExtension, IValueConverter {
public RadioButtonConverter(object optionValue)
=> OptionValue = optionValue;
public object OptionValue { get; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
=> value.Equals(OptionValue);
public object ConvertBack(object isChecked, Type targetType, object parameter, CultureInfo culture)
=> (bool)isChecked
? OptionValue
: Binding.DoNothing; // Only send value back if this is the checked option, otherwise do nothing
public override object ProvideValue(IServiceProvider serviceProvider)
=> this;
}
마법의 소스가 사용되고 있습니다.Binding.DoNothing
에서ConvertBack
기능.그 이후로RadioButton
컨트롤, '그룹'당 하나의 활성 옵션만 있을 수 있습니다(즉, 하나의 활성 옵션은IsChecked
로 설정한.true
), 우리는 단지 그것을 보장합니다.RadioButton
바인딩이 소스를 업데이트합니다.다른 사람들은RadioButton
인스턴스는 단순히 아무것도 하지 않습니다.
다음은 이를 사용하여 다음과 같은 방법으로int
OP가 요청한 값(아래 'cv'는 변환기 코드가 있는 가져온 네임스페이스이며 변환기에 전달하는 값은 특정 값입니다.RadioButton
를 나타냄)
<RadioButton Content="One" IsChecked="{Binding SomeIntProp, Converter={cv:RadioButtonConverter 1}}" />
<RadioButton Content="Two" IsChecked="{Binding SomeIntProp, Converter={cv:RadioButtonConverter 2}}" />
<RadioButton Content="Three" IsChecked="{Binding SomeIntProp, Converter={cv:RadioButtonConverter 3}}" />
바인딩 단순화
위에서 설명한 것은 반복되는 코드이며 90% 동안 바인딩이나 변환기를 사용하여 특별한 작업을 수행하지 않습니다.이와 같이, 다음과 같이 단순화해 보겠습니다.RadioButtonBinding
변환기를 설치합니다.여기 코드가 있습니다...
public class RadioButtonBinding : Binding {
public RadioButtonBinding(string path, object optionValue)
: base(path)
=> Converter = new RadioButtonConverter(optionValue);
}
이 새 바인딩을 사용하면 호출 사이트가 크게 간소화됩니다(여기서 'b'는 바인딩 코드가 있는 가져온 네임스페이스입니다).
<RadioButton Content="One" IsChecked="{b:RadioButtonBinding SomeIntProp, 1}" />
<RadioButton Content="Two" IsChecked="{b:RadioButtonBinding SomeIntProp, 2}" />
<RadioButton Content="Three" IsChecked="{b:RadioButtonBinding SomeIntProp, 3}" />
참고: Converter 인수도 설정하지 마십시오. 그렇지 않으면 이 인수를 사용하는 모든 요점이 실패하게 됩니다.
Enum 값에 바인딩
위의 예제에서는 기본 스칼라(예: 1, 2, 3)를 다루었습니다. 하지만 우리가 원하는 값이 다음과 같은 열거형이라면 어떻게 될까요?
public enum TestEnum {
yes,
no,
maybe,
noIdea
}
구문은 동일하지만 콜 사이트에서는 훨씬 더 장황하게 만들기 위해 바인딩하는 값을 보다 구체적으로 지정해야 합니다. (예를 들어, '예'만 전달하면 열거형이 아닌 문자열로 처리되므로 동등성 검사에 실패합니다.)
다음은 변환기 버전의 콜 사이트입니다(여기서 'v'는 열거값이 있는 가져온 네임스페이스입니다).
<RadioButton Content="Yes" IsChecked="{Binding SomeEnumProp, Converter={cv:RadioButtonConverter {x:Static v:TestEnum.yes}}}" />
<RadioButton Content="No" IsChecked="{Binding SomeEnumProp, Converter={cv:RadioButtonConverter {x:Static v:TestEnum.no}}}" />
<RadioButton Content="Maybe" IsChecked="{Binding SomeEnumProp, Converter={cv:RadioButtonConverter {x:Static v:TestEnum.maybe}}}" />
<RadioButton Content="No Idea" IsChecked="{Binding SomeEnumProp, Converter={cv:RadioButtonConverter {x:Static v:TestEnum.noIdea}}}" />
그리고 더 간단하지만, 여기 바인딩 버전의 콜 사이트가 있습니다. 더 낫지만, 여전히 장황합니다.
<RadioButton Content="Yes" IsChecked="{b:RadioButtonBinding SomeEnumProp, {x:Static v:TestEnum.yes}}" />
<RadioButton Content="No" IsChecked="{b:RadioButtonBinding SomeEnumProp, {x:Static v:TestEnum.no}}" />
<RadioButton Content="Maybe" IsChecked="{b:RadioButtonBinding SomeEnumProp, {x:Static v:TestEnum.maybe}}" />
<RadioButton Content="No Idea" IsChecked="{b:RadioButtonBinding SomeEnumProp, {x:Static v:TestEnum.noIdea}}" />
Enum-유형별 변형
많은 경우 특정 열거형에 바인딩될 것으로 알고 있는 경우 이전 변환기를 하위 분류하고 바인딩을 열거형 변형으로 하여 위 내용을 단순화할 수 있습니다.
아래는 정확하게 다음과 같은 작업을 수행합니다.TestEnum
위에서 정의한 것처럼...
// TestEnum-specific Converter
public class TestEnumConverter : RadioButtonConverter {
public TestEnumConverter(TestEnum optionValue)
: base(optionValue) {}
}
// TestEnum-specific Binding
public class TestEnumBinding : RadioButtonBinding {
public TestEnumBinding(string path, TestEnum value)
: base(path, value) { }
}
그리고 여기 콜 사이트들이...
<!- Converter Variants -->
<RadioButton Content="Yes" IsChecked="{Binding SomeTestEnumProp, Converter={cv:TestEnumConverter yes}}" />
<RadioButton Content="No" IsChecked="{Binding SomeTestEnumProp, Converter={cv:TestEnumConverter no}}" />
<RadioButton Content="Maybe" IsChecked="{Binding SomeTestEnumProp, Converter={cv:TestEnumConverter maybe}}" />
<RadioButton Content="No Idea" IsChecked="{Binding SomeTestEnumProp, Converter={cv:TestEnumConverter noIdea}}" />
<!- Binding Variants -->
<RadioButton Content="Yes" IsChecked="{b:TestEnumBinding SomeTestEnumProp, yes}" />
<RadioButton Content="No" IsChecked="{b:TestEnumBinding SomeTestEnumProp, no}" />
<RadioButton Content="Maybe" IsChecked="{b:TestEnumBinding SomeTestEnumProp, maybe}" />
<RadioButton Content="No Idea" IsChecked="{b:TestEnumBinding SomeTestEnumProp, noIdea}" />
보다시피 XAML 파서는 문자열에서 열거형으로의 변환을 자동으로 처리하므로 코드를 훨씬 쉽게 읽을 수 있습니다.그것보다 훨씬 간단할 수 없습니다! :)
참고 사항:보다 상세한 선언에서 열거값을 명시적으로 지정하는 버전의 한 가지 좋은 점은 열거형의 경우 자동 완성이 된다는 것입니다.문자열을 변환하는 열거형 특정 버전에서는 이러한 정보를 얻을 수 없습니다.그러나 잘못된 문자열 값을 사용하면 후자는 컴파일에 실패하므로 간략성 대 자동 완성 편의성의 트레이드오프가 됩니다.
새 클래스를 만들 필요가 없는 Aviad's Answer를 기반으로 첨부 속성을 만들었습니다.
public static class RadioButtonHelper
{
[AttachedPropertyBrowsableForType(typeof(RadioButton))]
public static object GetRadioValue(DependencyObject obj) => obj.GetValue(RadioValueProperty);
public static void SetRadioValue(DependencyObject obj, object value) => obj.SetValue(RadioValueProperty, value);
public static readonly DependencyProperty RadioValueProperty =
DependencyProperty.RegisterAttached("RadioValue", typeof(object), typeof(RadioButtonHelper), new PropertyMetadata(new PropertyChangedCallback(OnRadioValueChanged)));
private static void OnRadioValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is RadioButton rb)
{
rb.Checked -= OnChecked;
rb.Checked += OnChecked;
}
}
public static void OnChecked(object sender, RoutedEventArgs e)
{
if (sender is RadioButton rb)
{
rb.SetCurrentValue(RadioBindingProperty, rb.GetValue(RadioValueProperty));
}
}
[AttachedPropertyBrowsableForType(typeof(RadioButton))]
public static object GetRadioBinding(DependencyObject obj) => obj.GetValue(RadioBindingProperty);
public static void SetRadioBinding(DependencyObject obj, object value) => obj.SetValue(RadioBindingProperty, value);
public static readonly DependencyProperty RadioBindingProperty =
DependencyProperty.RegisterAttached("RadioBinding", typeof(object), typeof(RadioButtonHelper), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnRadioBindingChanged)));
private static void OnRadioBindingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is RadioButton rb && rb.GetValue(RadioValueProperty).Equals(e.NewValue))
{
rb.SetCurrentValue(RadioButton.IsCheckedProperty, true);
}
}
}
사용법 :
<RadioButton GroupName="grp1" Content="Value 1"
helpers:RadioButtonHelper.RadioValue="val1" helpers:RadioButtonHelper.RadioBinding="{Binding SelectedValue}"/>
<RadioButton GroupName="grp1" Content="Value 2"
helpers:RadioButtonHelper.RadioValue="val2" helpers:RadioButtonHelper.RadioBinding="{Binding SelectedValue}"/>
<RadioButton GroupName="grp1" Content="Value 3"
helpers:RadioButtonHelper.RadioValue="val3" helpers:RadioButtonHelper.RadioBinding="{Binding SelectedValue}"/>
<RadioButton GroupName="grp1" Content="Value 4"
helpers:RadioButtonHelper.RadioValue="val4" helpers:RadioButtonHelper.RadioBinding="{Binding SelectedValue}"/>
언급URL : https://stackoverflow.com/questions/1317891/simple-wpf-radiobutton-binding
'itsource' 카테고리의 다른 글
iOS 시뮬레이터 스크린샷은 어디에 저장됩니까? (0) | 2023.05.02 |
---|---|
node.js + express.js: mongodb/mongoose를 사용한 세션 처리 (0) | 2023.05.02 |
AssertionError: 데이터베이스 연결이 UTC로 설정되지 않았습니다. (0) | 2023.05.02 |
강력한 유형의 부분 뷰에 추가 뷰 데이터 전달 (0) | 2023.05.02 |
내 Bash 스크립트에 전달된 모든 인수를 내 함수로 전달하는 방법은 무엇입니까? (0) | 2023.04.27 |