2017-10-15 11 views
0

iOS에서 알려진 Segmented Control로 RadioButton을 수정했습니다.바인딩 스타일의 업데이트, RelevantSource

<Style TargetType="control:SegmentRadioButton" x:Key="SegmentedRadioButtonStyle"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="control:SegmentRadioButton"> 
       <Grid x:Name="RootGrid" Background="{TemplateBinding Background}"> 
        <ContentPresenter 
         x:Name="ContentPresenter" 
         Padding="{TemplateBinding Padding}" 
         HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" 
         VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" 
         AutomationProperties.AccessibilityView="Raw" 
         BorderThickness="{TemplateBinding BorderThickness}" 
         BorderBrush="{TemplateBinding BorderBrush}" 
         Content="{TemplateBinding Content}" 
         ContentTemplate="{TemplateBinding ContentTemplate}" 
         ContentTransitions="{TemplateBinding ContentTransitions}" 
         Background="{TemplateBinding Background}" 
         Foreground="{TemplateBinding Foreground}"/> 
        <VisualStateManager.VisualStateGroups> 
         <VisualStateGroup x:Name="CommonStates"> 
          <VisualState x:Name="Normal"> 
           <Storyboard> 
            <PointerUpThemeAnimation Storyboard.TargetName="RootGrid" /> 
           </Storyboard> 
          </VisualState> 
         </VisualStateGroup> 
         <VisualStateGroup x:Name="CheckStates"> 
          <VisualState x:Name="Checked"> 
           <Storyboard> 
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground"> 
             <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding SelectedTextColor, RelativeSource={RelativeSource TemplatedParent}}" /> 
            </ObjectAnimationUsingKeyFrames> 
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background"> 
             <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding TintColor, RelativeSource={RelativeSource TemplatedParent}}" /> 
            </ObjectAnimationUsingKeyFrames> 
           </Storyboard> 
          </VisualState> 
          <VisualState x:Name="Unchecked"> 
           <Storyboard> 
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground"> 
             <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding Foreground, RelativeSource={RelativeSource TemplatedParent}}" /> 
            </ObjectAnimationUsingKeyFrames> 
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background"> 
             <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding Background, RelativeSource={RelativeSource TemplatedParent}}" /> 
            </ObjectAnimationUsingKeyFrames> 
           </Storyboard> 
          </VisualState> 
          <VisualState x:Name="Indeterminate" /> 
         </VisualStateGroup> 
        </VisualStateManager.VisualStateGroups> 
       </Grid> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

그리고 내 유도 제어는 다음과 같습니다 :

public class SegmentRadioButton : RadioButton 
{ 
    public static readonly DependencyProperty SelectedTextColorProperty = DependencyProperty.Register(
     "SelectedTextColor", 
     typeof(SolidColorBrush), typeof(SegmentRadioButton), 
     new PropertyMetadata(default(SolidColorBrush), new PropertyChangedCallback(OnSelectedTextChanged))); 

    public SolidColorBrush SelectedTextColor 
    { 
     get => (SolidColorBrush) GetValue(SelectedTextColorProperty); 
     set => SetValue(SelectedTextColorProperty, value); 
    } 

    public static readonly DependencyProperty TintColorProperty = DependencyProperty.Register(
     "TintColor", typeof(SolidColorBrush), typeof(SegmentRadioButton), new PropertyMetadata(default(SolidColorBrush), new PropertyChangedCallback(OnTintChanged))); 

    public SolidColorBrush TintColor 
    { 
     get => (SolidColorBrush) GetValue(TintColorProperty); 
     set => SetValue(TintColorProperty, value); 
    } 

    public SegmentRadioButton() 
    { 

    } 

    private static void OnTintChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     if (d is SegmentRadioButton segment) 
     { 
      segment.BorderBrush = (SolidColorBrush) e.NewValue; 

      if (segment.IsChecked ?? false) 
      { 
       // Hack to make the selected segment re-draw. 
       segment.IsChecked = false; 
       segment.IsChecked = true; 
      } 
     } 
    } 

    private static void OnSelectedTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     if (d is SegmentRadioButton segment) 
     { 
      if (segment.IsChecked ?? false) 
      { 
       // Hack to make the selected segment re-draw. 
       segment.IsChecked = false; 
       segment.IsChecked = true; 
      } 
     } 
    } 

} 

질문 :이 실제로 작동 enter image description here

내 수정 된 스타일은 다음과 같습니다 : 여기

는 모습입니다 ,하지만 내가 더 우아하고 덜 궁금 해서요 해킹 t 만드는 방법 그는 TintColorSelectedTextColor로 업데이트 하시겠습니까? 두 개의 인라인 코멘트에서 볼 수 있듯이 IsChecked 값을 반전하여 다시 그리거나 다시 그려야합니다.

+0

나는 아무 문제가 없다 생각합니다. "IsChecked"속성을 false로 설정하고 컨트롤 템플릿에서 "Checked"시각적 상태를 트리거하는 true로 재설정합니다. 그런 다음 컨트롤이 적시에 색을 업데이트 할 수 있습니다. – Skyblue

+0

네, 그게 효과가 있지만 조금 해킹 된 것 같아요. 대신 Visual State Manager를 사용하여 끝 냈습니다. 그것은 여전히 ​​약간의 해킹을 느낀다. 그러나 나는 생각한다. –

답변

1

Visual State Manager와 간단한 새로 고침을 사용하여 끝났습니다.

코드는 GitHub의에 : 지금 보이는 여기

Plugin.SegmentedControl 코드의 핵심 부분입니다 :

public class SegmentRadioButton : RadioButton 
{ 
    public static readonly DependencyProperty SelectedTextColorProperty = DependencyProperty.Register(
     "SelectedTextColor", 
     typeof(SolidColorBrush), typeof(SegmentRadioButton), 
     new PropertyMetadata(default(SolidColorBrush), new PropertyChangedCallback(OnSelectedTextChanged))); 

    public SolidColorBrush SelectedTextColor 
    { 
     get => (SolidColorBrush) GetValue(SelectedTextColorProperty); 
     set => SetValue(SelectedTextColorProperty, value); 
    } 

    public static readonly DependencyProperty TintColorProperty = DependencyProperty.Register(
     "TintColor", typeof(SolidColorBrush), typeof(SegmentRadioButton), new PropertyMetadata(default(SolidColorBrush), new PropertyChangedCallback(OnTintChanged))); 

    public SolidColorBrush TintColor 
    { 
     get => (SolidColorBrush) GetValue(TintColorProperty); 
     set => SetValue(TintColorProperty, value); 
    } 

    public static readonly DependencyProperty DisabledColorProperty = DependencyProperty.Register(
     "DisabledColor", typeof(SolidColorBrush), typeof(SegmentRadioButton), new PropertyMetadata(default(SolidColorBrush), new PropertyChangedCallback(OnDisabledColorChanged))); 

    public SolidColorBrush DisabledColor 
    { 
     get => (SolidColorBrush) GetValue(DisabledColorProperty); 
     set => SetValue(DisabledColorProperty, value); 
    } 


    public SegmentRadioButton() 
    { 
     this.IsEnabledChanged += SegmentRadioButton_IsEnabledChanged; 
    } 

    private void SegmentRadioButton_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e) 
    { 
     if (sender is SegmentRadioButton segment) 
     { 
      Refresh(segment); 
     } 
    } 

    private static void OnTintChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     if (d is SegmentRadioButton segment) 
     { 
      segment.BorderBrush = (SolidColorBrush) e.NewValue; 
      Refresh(segment); 
     } 
    } 


    private static void OnDisabledColorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     if (d is SegmentRadioButton segment) 
     { 
      segment.BorderBrush = (SolidColorBrush)e.NewValue; 
      Refresh(segment); 
     } 
    } 

    private static void OnSelectedTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     if (d is SegmentRadioButton segment) 
     { 
      Refresh(segment); 
     } 
    } 

    private static void Refresh(SegmentRadioButton segment) 
    { 
     // Go to "Indeterminate" State to ensure that the GotoState is refreshed even if the state is the same. 
     // Necessary because properties might have changed even when the state have not. 

     VisualStateManager.GoToState(segment, "Indeterminate", false); 

     if (segment.IsChecked ?? false) 
     { 
      VisualStateManager.GoToState(segment, segment.IsEnabled ? "Checked" : "DisabledAndChecked", false); 
     } 
     else 
     { 
      VisualStateManager.GoToState(segment, segment.IsEnabled ? "Unchecked" : "DisabledAndUnchecked", false); 
     } 
    } 
} 

스타일 :

<Style TargetType="control1:SegmentRadioButton" x:Key="SegmentedRadioButtonStyle"> 
    <Setter Property="UseSystemFocusVisuals" Value="True" /> 
    <Setter Property="VerticalContentAlignment" Value="Center"></Setter> 
    <Setter Property="HorizontalContentAlignment" Value="Center"/> 
    <Setter Property="Padding" Value="8,4,8,4"></Setter> 
    <Setter Property="Background" Value="Transparent"></Setter> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="control1:SegmentRadioButton"> 
       <Grid x:Name="RootGrid" Background="{TemplateBinding Background}"> 
        <ContentPresenter 
         x:Name="ContentPresenter" 
         Padding="{TemplateBinding Padding}" 
         HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" 
         VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" 
         AutomationProperties.AccessibilityView="Raw" 
         BorderThickness="{TemplateBinding BorderThickness}" 
         BorderBrush="{TemplateBinding BorderBrush}" 
         Content="{TemplateBinding Content}" 
         ContentTemplate="{TemplateBinding ContentTemplate}" 
         ContentTransitions="{TemplateBinding ContentTransitions}" 
         Background="{TemplateBinding Background}" 
         Foreground="{TemplateBinding Foreground}"/> 
        <VisualStateManager.VisualStateGroups> 
         <VisualStateGroup x:Name="CommonStates"> 
          <VisualState x:Name="Normal"> 
           <Storyboard> 
            <PointerUpThemeAnimation Storyboard.TargetName="RootGrid" /> 
           </Storyboard> 
          </VisualState> 
          <VisualState x:Name="DisabledAndChecked"> 
           <Storyboard> 
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush"> 
             <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding DisabledColor, RelativeSource={RelativeSource TemplatedParent}}" /> 
            </ObjectAnimationUsingKeyFrames> 
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground"> 
             <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding SelectedTextColor, RelativeSource={RelativeSource TemplatedParent}}" /> 
            </ObjectAnimationUsingKeyFrames> 
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background"> 
             <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding DisabledColor, RelativeSource={RelativeSource TemplatedParent}}" /> 
            </ObjectAnimationUsingKeyFrames> 
           </Storyboard> 
          </VisualState> 
          <VisualState x:Name="DisabledAndUnchecked"> 
           <Storyboard> 
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush"> 
             <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding DisabledColor, RelativeSource={RelativeSource TemplatedParent}}" /> 
            </ObjectAnimationUsingKeyFrames> 
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground"> 
             <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding DisabledColor, RelativeSource={RelativeSource TemplatedParent}}" /> 
            </ObjectAnimationUsingKeyFrames> 
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background"> 
             <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding Background, RelativeSource={RelativeSource TemplatedParent}}" /> 
            </ObjectAnimationUsingKeyFrames> 
           </Storyboard> 
          </VisualState> 
         </VisualStateGroup> 
         <VisualStateGroup x:Name="CheckStates"> 
          <VisualState x:Name="Checked"> 
           <Storyboard> 
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush"> 
             <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding TintColor, RelativeSource={RelativeSource TemplatedParent}}" /> 
            </ObjectAnimationUsingKeyFrames> 
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground"> 
             <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding SelectedTextColor, RelativeSource={RelativeSource TemplatedParent}}" /> 
            </ObjectAnimationUsingKeyFrames> 
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background"> 
             <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding TintColor, RelativeSource={RelativeSource TemplatedParent}}" /> 
            </ObjectAnimationUsingKeyFrames> 
           </Storyboard> 
          </VisualState> 
          <VisualState x:Name="Unchecked"> 
           <Storyboard> 
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush"> 
             <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding TintColor, RelativeSource={RelativeSource TemplatedParent}}" /> 
            </ObjectAnimationUsingKeyFrames> 
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground"> 
             <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding TintColor, RelativeSource={RelativeSource TemplatedParent}}" /> 
            </ObjectAnimationUsingKeyFrames> 
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background"> 
             <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding Background, RelativeSource={RelativeSource TemplatedParent}}" /> 
            </ObjectAnimationUsingKeyFrames> 
           </Storyboard> 
          </VisualState> 

          <VisualState x:Name="Indeterminate" /> 
         </VisualStateGroup> 
        </VisualStateManager.VisualStateGroups> 
       </Grid> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style>