2010-04-13 4 views
29

나는 파란색 선으로DataGridTextColumn의 스타일을 지정할 수없는 이유는 무엇입니까?

<Style TargetType="{x:Type DataGridTextColumn}"> 
      ... 
</Style> 

그러나 다음 코드, 비주얼 스튜디오 2010의 하이라이트 {x:Type DataGridTextColumn}DataGridTextColumn의 스타일을 만들려고하고 부연 : Exception has been thrown by the target of an invocation.

왜 이런 일이 않습니다이며 어떻게 해결합니까 ?

+0

Ray의 솔루션이 효과가 있습니까? 만약 그렇다면 나는 약간의 샘플 코드를보고 싶다. 여기서 얻지 못하는 부분은 해당 스타일의 TargetType이 FrameworkElement이므로 CanUserSort = False와 같은 속성을 어떻게 설정할 수 있습니까? 건배 – Berryl

+0

여기에 또 다른 방법입니다 ... http://stackoverflow.com/questions/21982526/show-missing-part-of-text-in-datagrid-textbox-wpf –

답변

18

. FrameworkElement 등은 스타일링 만 지원합니다.

XAML에서 FrameworkElement 또는 FrameworkContentElement이 아닌 형식의 스타일을 만들려고하면 해당 오류 메시지가 나타납니다.

어떻게 해결할 수 있습니까? 어떤 문제와 마찬가지로, 의지가있는 곳이 있습니다.

public class MyDataGridHelper : DependencyObject 
{ 
    // Use propa snipped to create attached TextColumnStyle with metadata: 
    ... RegisterAttached("TextColumnStyle", typeof(Style), typeof(MyDataGridHelper), new PropertyMetadata 
    { 
    PropertyChangedCallback = (obj, e) => 
    { 
     var grid = (DataGrid)obj; 
     if(e.OldValue==null && e.NewValue!=null) 
     grid.Columns.CollectionChanged += (obj2, e2) => 
     { 
      UpdateColumnStyles(grid); 
     } 
    } 
    } 
    private void UpdateStyles(DataGrid grid) 
    { 
    var style = GetTextColumnStyle(grid); 
    foreach(var column in grid.Columns.OfType<DataGridTextColumn>()) 
     foreach(var setter in style.Setters.OfType<Setter>()) 
     if(setter.Value is BindingBase) 
      BindingOperations.SetBinding(column, setter.Property, setter.Value); 
     else 
      column.SetValue(setter.Property, setter.Value); 
    } 
} 

이 작동하는 방법은 다음과 같습니다

<DataGrid ...> 
    <local:MyDataGridHelper.TextColumnStyle> 
    <Style TargetType="FrameworkElement"> 
     ... setters here ... 
    </Style> 
    </local:MyDataGridHelper.TextColumnStyle> 
    ... 

이 구현은이 라인을 따라 뭔가 될 것이다 :이 경우에는 내가 가장 쉬운 솔루션은 데이터 그리드가되는 DataGridColumn 스타일을 지정하는 연결된 속성을 만드는 것입니다 생각 연결된 속성이 변경 될 때마다 표의 Columns.CollectionChanged 이벤트에 대한 처리기가 추가됩니다. CollectionChanged 이벤트가 발생하면 모든 열이 설정된 스타일로 업데이트됩니다.

위의 코드는 스타일이 제거되고 정상적으로 다시 추가되는 상황을 처리하지 않습니다. 두 개의 이벤트 처리기가 등록됩니다. 정말 견고한 솔루션의 경우 이벤트 처리기를 포함하는 다른 첨부 속성을 추가하여이 문제를 해결할 수 있으므로 이벤트 처리기를 등록 취소 할 수는 있지만 귀하의 목적에 따라 중요하지 않다고 생각합니다.

SetBinding 및 SetValue를 직접 사용하면 DefaultStyle 대신 BaseValueSource가 Local 인 DependencyProperty가 생성됩니다. 이것은 아마도 귀하의 경우에는 아무런 차이가 없지만 나는 그것을 언급해야한다고 생각했습니다.

+0

해결 방법을 설명하는 것이 좋습니다. 문제는 해결 방법입니다. –

+0

이 경우 트리거는 어떻게됩니까? 평소와 같이 작동합니까? – Caesar

2

는 스타일링 DataGrids를위한 치트 시트처럼,이 링크에서보세요 : FrameworkElement (또는 FrameworkContentElement)에서 파생하지 않는 DataGridTextColumnDataGridTextColumn 때문에 당신은 스타일을 할 수

http://blogs.msdn.com/jaimer/archive/2009/01/20/styling-microsoft-s-wpf-datagrid.aspx

+0

감사합니다,하지만 DataGridColumn DataGridColumnHeaders 만) – Nike

+0

셀을 스타일 한 다음 해당 셀을 열에 바인딩 할 수 있습니까? 목록 상자에서와 동일합니다. – deanvmc

+0

이 링크 : http://www.codeproject.com/KB/WPF/WPFDataGridExamples.aspx#templates에는 열 템플릿을 사용하여 실제 열의 스타일을 지정하는 데 대한 자세한 내용이 있습니다. – deanvmc

-5

DataGridTextColumn은 TextBlock이있는 열일뿐입니다. TargetType이 TextBlock 인 스타일을 작성하고 DataGridTextColumn의 ElementStyle 속성을 바인딩합니다. 희망이 도움이됩니다!

+0

TextBlock은 System.Windows.Controls.Control이 아니므로 작동하지 않습니다. –

-1

더 간단 :

<FontFamily x:Key="DefaultFont">Snap ITC</FontFamily> 
<Style x:Key="ControlStyle" TargetType="Control"> 
    <Setter Property="FontFamily" Value="{StaticResource DefaultFont}"/> 
</Style> 
<Style TargetType="{x:Type DataGridCellsPresenter}" BasedOn="{StaticResource ControlStyle}"> 
</Style> 
+1

이것은 제기 된 질문에 대한 일반적인 해결책이 결코 아닙니다. 또한 코드를 삭제하는 대신 제안 된 솔루션의 의도가 무엇인지 설명했다면 더 도움이 될 것입니다. –

4

스타일 태그는 올바른 장소에 가야한다. 귀하의 데이터 그리드는 지금이 바로 같은 것을 보일 수 있습니다 : 당신은 처음에 작동하지 않습니다 DataGridTextColumn 요소 내에 직접 스타일 태그를 추가 할 수

<DataGrid> 
     <DataGrid.Columns> 
      <DataGridTextColumn /> 
     </DataGrid.Columns> 
    </DataGrid> 

. 그러나 "DataGridTextColumn"요소 내에서 "DataGridTextColumn.ElementStyle"및/또는 "DataGridTextColumn.EditingElementStyle"에 대한 요소를 만들 수 있습니다.그 요소 태그의 각각은 그 안에 스타일 태그를 가질 수 있습니다

<DataGrid> 
     <DataGrid.Columns> 
      <DataGridTextColumn> 
       <DataGridTextColumn.ElementStyle> 
        <Style TargetType="TextBlock"> 
         <Setter Property="Background" Value="Green"></Setter> 
        </Style> 
       </DataGridTextColumn.ElementStyle> 
       <DataGridTextColumn.EditingElementStyle> 
        <Style TargetType="TextBox"> 
         <Setter Property="Background" Value="Orange"></Setter> 
        </Style> 
       </DataGridTextColumn.EditingElementStyle> 
      </DataGridTextColumn> 
     </DataGrid.Columns> 
    </DataGrid> 

한 스타일이보기에 적용되고 셀이 편집 모드에있을 때 다른 적용됩니다. 편집 할 때 TextBox로 보았을 때 TextBlock에서 변경된다는 점에 유의하십시오 (이것은 처음에 나를 잡았습니다!).

0

이것은 레이 번스의 대답에 더 많은 내용이 추가되었습니다. 처음에는 그것을 직접 구현할 수 없었지만 mm8 (https://stackoverflow.com/a/46690951/5381620)의 도움으로 실행 해 보았습니다. 정말 잘 작동합니다. 첨부 된 속성 접근 방식을 따르는 데 문제가있는 다른 사람들에게 전체 코드 스 니펫이 도움이 될 수 있습니다.

public class MyDataGridHelper : DependencyObject 
{ 
    private static readonly DependencyProperty TextColumnStyleProperty = DependencyProperty.RegisterAttached("TextColumnStyle", typeof(Style), typeof(MyDataGridHelper), new PropertyMetadata 
    { 
     PropertyChangedCallback = (obj, e) => 
     { 
      var grid = (DataGrid)obj; 
      if (e.OldValue == null && e.NewValue != null) 
       grid.Columns.CollectionChanged += (obj2, e2) => 
       { 
        UpdateColumnStyles(grid); 
       }; 
     } 
    }); 

    public static void SetTextColumnStyle(DependencyObject element, Style value) 
    { 
     element.SetValue(TextColumnStyleProperty, value); 
    } 
    public static Style GetTextColumnStyle(DependencyObject element) 
    { 
     return (Style)element.GetValue(TextColumnStyleProperty); 
    } 

    private static void UpdateColumnStyles(DataGrid grid) 
    { 
     var origStyle = GetTextColumnStyle(grid); 
     foreach (var column in grid.Columns.OfType<DataGridTextColumn>()) 
     { 
      //may not add setters to a style which is already in use 
      //therefore we need to create a new style merging 
      //original style with setters from attached property 
      var newStyle = new Style(); 
      newStyle.BasedOn = column.ElementStyle; 
      newStyle.TargetType = origStyle.TargetType; 

      foreach (var setter in origStyle.Setters.OfType<Setter>()) 
      { 
       newStyle.Setters.Add(setter); 
      } 

      column.ElementStyle = newStyle; 
     } 
    } 
} 

XAML

<Grid> 
    <DataGrid Name="MyDataGrid" ItemsSource="{Binding Lines}" AutoGenerateColumns="False" > 
     <local:MyDataGridHelper.TextColumnStyle> 
      <Style TargetType="TextBlock"> 
       <Setter Property="TextWrapping" Value="Wrap"/> 
      </Style> 
     </local:MyDataGridHelper.TextColumnStyle> 
     <DataGrid.Columns> 
      <DataGridTextColumn Header="ProductId1" Binding="{Binding Path=Result1}" /> 
      <DataGridTextColumn Header="ProductId2" Binding="{Binding Path=Result2}" /> 
     </DataGrid.Columns> 
    </DataGrid> 
</Grid> 

편집 : 첫 번째 방법에서 나는 전체 스타일을 덮어 않았다. 새 버전에서는이 같은 다른 스타일 수정을 유지할 수 있습니다.

<DataGridTextColumn.ElementStyle> 
    <Style TargetType="{x:Type TextBlock}"> 
     <Setter Property="Foreground" Value="Red"/> 
    </Style> 
</DataGridTextColumn.ElementStyle> 
관련 문제