2014-04-07 5 views
4

TextBox 및 ComboBox를 비롯한 여러 컨트롤이 있고 모두 해당 유효성 검사에 포함 된 모든 오류와 함께 도구 설명을 표시하고 싶습니다. . 오류 컬렉션. 가능하다면 그들 모두가 공통된 스타일을 공유하고 싶습니다. 이것이 제가 시도하는 것입니다. ToolTip 설정 도구에서 제 바인딩에 문제가 있다고 확신하지만 무엇을 알아 내지 못합니다. 오류 (오류 또는 경고)의 심각도를 지정하는 INotifyDataErrorInfo 구현에서 Error 객체를 반환합니다.WPF 4.5에서 INotifyDataErrorInfo를 사용하는 컨트롤에 대해 모든 Validation.Errors를 표시하는 도구 설명 만들기

그 컨트롤에 대한 모든 오류 및 경고 목록을 포함하는 툴팁을 표시하는 모든 컨트롤에 적용되는 스타일을 갖고 싶습니다. 오류는 빨간색으로 표시되고 경고는 노란색으로 표시되어야합니다. 내가 AncestorLevel 1에서 모두 제어의 AncestoryType 검색이의 2 없음 작동하는 것 같다 없습니다하는 RelativeSource를 변경 시도

 <Style TargetType="FrameworkElement"> 
     <Setter Property="ToolTip"> 
      <Setter.Value> 
       <ItemsControl ItemsSource="{Binding Path=(Validation.Errors), RelativeSource={RelativeSource Self}}"> 
        <ItemsControl.ItemTemplate> 
         <DataTemplate> 
          <TextBlock Text="{Binding ErrorContent.ErrorMessage}"> 
           <TextBlock.Style> 
            <Style TargetType="TextBlock"> 
             <Setter Property="Foreground" Value="Red"/> 
             <Style.Triggers> 
              <DataTrigger Binding="{Binding ErrorContent.ErrorSeverity}" 
                  Value="{x:Static local:ErrorType.Warning}"> 
               <Setter Property="Foreground" Value="Yellow"/> 
              </DataTrigger> 
             </Style.Triggers> 
            </Style> 
           </TextBlock.Style> 
          </TextBlock> 
         </DataTemplate> 
        </ItemsControl.ItemTemplate> 
       </ItemsControl> 
      </Setter.Value> 
     </Setter> 
     <Style.Triggers> 
      <DataTrigger Binding="{Binding Path=(Validation.HasError)}" Value="True"> 
       <Setter Property="ToolTip"> 
        <Setter.Value> 
         <ItemsControl ItemsSource="{Binding Path=(Validation.Errors)}"> 
          <ItemsControl.ItemTemplate> 
           <DataTemplate> 
            <TextBlock Text="{Binding ErrorContent.ErrorMessage}"> 
             <TextBlock.Style> 
              <Style TargetType="TextBlock"> 
               <Setter Property="Foreground" Value="Red"/> 
               <Style.Triggers> 
                <DataTrigger Binding="{Binding ErrorContent.ErrorSeverity}" 
                  Value="{x:Static local:ErrorType.Warning}"> 
                 <Setter Property="Foreground" Value="Yellow"/> 
                </DataTrigger> 
               </Style.Triggers> 
              </Style> 
             </TextBlock.Style> 
            </TextBlock> 
           </DataTemplate> 
          </ItemsControl.ItemTemplate> 
         </ItemsControl> 
        </Setter.Value> 
       </Setter> 
      </DataTrigger> 
     </Style.Triggers> 
    </Style> 

: 여기에 와서 한 스타일이다.

나는 ErrorTemplate에 사용했던 ControlTemplate의 스타일을 기반으로합니다. ErrorTemplate은 거의 동일한 작업을 수행합니다. 오류 심각도에 따라 빨간색 또는 노란색 경계선을 표시하고 해당 항목에 대해 정확하게 수행 한 것과 같은 툴팁을 표시합니다. 컨트롤 자체에 대한 도구 설명. ErrorTemplate이 자동으로 DataContext를 Validation.Errors 컬렉션으로 설정하여 ItmesCollection의 ItemsSource를 쉽게 바인딩 할 수 있기 때문에 내 바인딩과 관련이 있다고 확신합니다. 스타일에 대한 툴팁에는 그러한 행운이 없습니다. 여기에 내 ErrorTemplate에 사용되는 작업 ControlTemplate입니다 :

 <ControlTemplate x:Key="ErrorTemplate"> 
     <Border BorderThickness="1"> 
      <AdornedElementPlaceholder Name="ElementPlaceholder"/> 
      <Border.Style> 
       <Style TargetType="Border"> 
        <Setter Property="BorderBrush" Value="Red"/> 
        <Style.Triggers> 
         <DataTrigger Binding="{Binding ElementName=ElementPlaceholder, Path=AdornedElement.(Validation.Errors)[0].ErrorContent.ErrorSeverity}" 
             Value="{x:Static local:ErrorType.Warning}"> 
          <Setter Property="BorderBrush" Value="Yellow"/> 
         </DataTrigger> 
        </Style.Triggers> 
       </Style> 
      </Border.Style> 
      <Border.ToolTip> 
       <ItemsControl ItemsSource="{Binding}"> 
        <ItemsControl.ItemTemplate> 
         <DataTemplate> 
          <TextBlock Text="{Binding ErrorContent.ErrorMessage}"> 
           <TextBlock.Style> 
            <Style TargetType="TextBlock"> 
             <Setter Property="Foreground" Value="Red"/> 
             <Style.Triggers> 
              <DataTrigger Binding="{Binding ErrorContent.ErrorSeverity}" 
                  Value="{x:Static local:ErrorType.Warning}"> 
               <Setter Property="Foreground" Value="Yellow"/> 
              </DataTrigger> 
             </Style.Triggers> 
            </Style> 
           </TextBlock.Style> 
          </TextBlock> 
         </DataTemplate> 
        </ItemsControl.ItemTemplate> 
       </ItemsControl> 
      </Border.ToolTip> 
     </Border> 
    </ControlTemplate> 

누구든지 내게 어떤 제안을 줄 수 있습니까?

답변

5

꽤 오랜 시간 동안 이것을 알아 내려고 시도한 끝에 마침내 오른쪽 경로로 나를 안내 한 post on the MSDN forums을 우연히 발견했습니다. 우선, 나는 원했던 각각의 TargetType에 대해 Styles를 지정하고 원본에 기초를 둘 필요가 있었다. 둘째, 문제는 제 바인딩에있는 것이 아니라 바인딩 된 컬렉션이 업데이트되지 않았다는 것을 깨달았습니다. XAML에 지정된 경우 ListBox/ItemsControl이 업데이트되지 않는 이유는 모르지만 변환기에서 지정하면 작동합니다. 여기

 <Style TargetType="Control" x:Key="ErrorToolTip"> 
     <Style.Resources> 
      <Style TargetType="ListBoxItem"> 
       <Setter Property="Template"> 
        <Setter.Value> 
         <ControlTemplate> 
          <TextBlock Text="{Binding ErrorContent.ErrorMessage}" 
             Background="Transparent"> 
           <TextBlock.Style> 
            <Style TargetType="TextBlock"> 
             <Setter Property="Foreground" Value="Red"/> 
             <Style.Triggers> 
              <DataTrigger Binding="{Binding ErrorContent.ErrorSeverity}" 
                 Value="{x:Static local:ErrorType.Warning}"> 
               <Setter Property="Foreground" Value="Orange" /> 
              </DataTrigger> 
             </Style.Triggers> 
            </Style> 
           </TextBlock.Style> 
          </TextBlock> 
         </ControlTemplate> 
        </Setter.Value> 
       </Setter> 
      </Style> 
     </Style.Resources> 
     <Style.Triggers> 
      <Trigger Property="Validation.HasError" Value="True"> 
       <Setter Property="ToolTip" 
         Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors), Converter={StaticResource ErrorCollectionConverter}}"> 
       </Setter> 
      </Trigger> 
     </Style.Triggers> 
    </Style> 
    <Style TargetType="TextBox" BasedOn="{StaticResource ErrorToolTip}"/> 
    <Style TargetType="ComboBox" BasedOn="{StaticResource ErrorToolTip}"/> 

그리고 내 컨버터 기능입니다 : :이 내 같은 문제가있는 거기 어떤 다른 사람에게 도움이 희망

 public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value == null) return null; 
     return new ListBox 
     { 
      ItemsSource = (ReadOnlyObservableCollection<ValidationError>) value, 
      BorderThickness = new Thickness(0), 
      Background = Brushes.Transparent 
     }; 
    } 

가 여기 내 새로운 스타일이다. 왜 이렇게 큰 차이가 나는지 누군가가 알고 있으면 나는 알고 싶어합니다.

1

이것은 내가 사용한 Matts 대답의 단순화 된 버전입니다. 이 메시지는 TextBox 유형의 컨트롤에서만 작동하며 오류 심각도는 사용하지 않습니다. 사용자가 입력 한 디렉토리 경로 컨텍스트에서 하나 이상의 오류를 표시해야하는 경우에 사용됩니다. Matts 대답과는 달리 DisplayMemberPath = "ErrorContent" 변환기에서 직접 오류에 액세스했습니다.


추가 된 특성 Validation.HasError에 해당하는 툴팁을 표시하는 TextBox의 스타일 :

<UserControl.Resources> 
    <ui:ErrorCollectionConverter x:Key="ErrorCollectionConverter"></ui:ErrorCollectionConverter> 
    <Style TargetType="TextBox"> 
     <Style.Triggers> 
      <Trigger Property="Validation.HasError" Value="True"> 
       <Setter Property="ToolTip" 
        Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors), Converter={StaticResource ErrorCollectionConverter}}"> 
       </Setter> 
      </Trigger> 
     </Style.Triggers> 
    </Style> 
</UserControl.Resources> 

내 "디렉토리" TextBox이 암시 적으로 사용하여 스타일 :

<TextBox Text="{Binding Directory, UpdateSourceTrigger=PropertyChanged, ValidatesOnNotifyDataErrors=True}"></TextBox> 

값 컨버터는 ErrorContent 속성에 직접 액세스합니다.

internal class ErrorCollectionConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value == null) return null; 
     return new ListBox 
     { 
      ItemsSource = (ReadOnlyObservableCollection<ValidationError>)value, 
      BorderThickness = new Thickness(0), 
      Background = Brushes.Transparent, 
      DisplayMemberPath = "ErrorContent" 
     }; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 
3

이것은 훨씬 쉽게 달성 될 수 있습니다.

당신은 위와 같이 "도구 설명"에 바인딩 작성하는 경우 :

<Trigger Property="Validation.HasError" Value="True"> 
     <Setter Property="ToolTip" 
       Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors), Converter={StaticResource ErrorCollectionConverter}}"> 
     </Setter> 
</Trigger> 

은 "기적적으로"바인딩 실제로 툴팁의 "PlacementTarget"자신을 바인딩합니다. 따라서 컨트롤에 붙어 있습니다.

당신이 아래에 할 수있는 항목의 전체 목록을 표시해야하는 경우 :

<Trigger Property="Validation.HasError" Value="True"> 
     <Setter Property="ToolTip"> 
      <Setter.Value> 
       <ToolTip DataContext="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget}"> 
        <ItemsControl ItemsSource="{Binding Path=(Validation.Errors)}" DisplayMemberPath="ErrorContent" /> 
       </ToolTip> 
      </Setter.Value> 
     </Setter> 
</Trigger> 

당신은 심지어 ItemsControl에서 직접 PlacementTarget에 도구 설명 개체를 삭제하고 결합 할 수있다. 그런 다음 ItemsControl에서 AncestorType을 통해 RelativeSource로 툴팁을 사용하십시오.

희망이 도움이됩니다.