2010-04-13 30 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

क्या रे का समाधान आपके लिए काम करता था? अगर ऐसा होता तो मुझे कुछ नमूना कोड देखना अच्छा लगेगा। जिस भाग में मुझे यहां नहीं मिलता है वह यह है कि स्टाइल के लिए टार्गेट टाइप फ्रेमवर्क एलिमेंट है, तो उदाहरण के लिए, आप CanUserSort = False जैसी संपत्ति कैसे सेट कर सकते हैं? चीयर्स – Berryl

+0

यहां एक और तरीका है ... http://stackoverflow.com/questions/21982526/show-missing-part-of-text-in-datagrid-textbox-wpf –

उत्तर

18

आप DataGridTextColumn क्योंकि DataGridTextColumnFrameworkElement (या FrameworkContentElement) से निकाले जाते हैं नहीं है शैली नहीं दे सकते। केवल फ्रेमवर्क एलिमेंट, आदि स्टाइल का समर्थन करता है।

जब आप किसी भी प्रकार के लिए XAML में शैली बनाने का प्रयास करते हैं जो FrameworkElement या FrameworkContentElement नहीं है तो आपको वह त्रुटि संदेश मिलता है।

आप इसे कैसे हल करते हैं? किसी भी समस्या के साथ, जहां इच्छा है वहां एक रास्ता है। इस मामले में मुझे लगता है कि सबसे आसान समाधान डेटा ग्रिड एक DataGridColumn शैली आवंटित करने के लिए के लिए एक संलग्न संपत्ति बनाने के लिए है:

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> 
    ... 

कार्यान्वयन इन पंक्तियों के साथ कुछ होगा , किसी भी समय संलग्न संपत्ति बदल दी जाती है, कॉलम के लिए एक हैंडलर जोड़ा जाता है। ग्रिड पर चयन परिवर्तन घटना। जब संग्रहChanged घटना आग लगती है, सभी कॉलम सेट की गई शैली के साथ अद्यतन कर रहे हैं।

ध्यान दें कि उपरोक्त कोड उस स्थिति को संभाल नहीं करता है जहां एक शैली को हटाया जाता है और फिर से जोड़ा जाता है: दो ईवेंट हैंडलर पंजीकृत होते हैं। वास्तव में एक मजबूत समाधान के लिए आप ईवेंट हैंडलर युक्त एक और संलग्न संपत्ति जोड़कर इसे ठीक करना चाहते हैं ताकि ईवेंट हैंडलर को अनियंत्रित किया जा सके, लेकिन आपके उद्देश्य के लिए मुझे लगता है कि यह महत्वहीन है।

यहां एक और चेतावनी यह है कि सेटबाइंडिंग और सेटवैल्यू का सीधा उपयोग निर्भरता प्रॉपर्टी को के बजाय Local का बेसवेल्यूसोर्स का कारण बन जाएगा। इससे शायद आपके मामले में कोई फर्क नहीं पड़ता लेकिन मैंने सोचा कि मुझे इसका जिक्र करना चाहिए।

+0

कामकाज समझाते हुए अच्छी नौकरी, यह चेतावनी है और उन्हें कैसे ठीक किया जाए। –

+0

इस मामले में ट्रिगर्स के बारे में क्या, क्या वे सामान्य रूप से काम करेंगे? – Caesar

2

अपने स्टाइल datagrids के लिए नकल पुस्तिकाओं की तरह, इस लिंक पर एक नज़र डालें:

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

+0

धन्यवाद, लेकिन डेटाग्रिड कॉलम स्टाइल के बारे में कुछ भी नहीं है (केवल DataGridColumnHeaders) – Nike

+0

क्या आप सेल को स्टाइल नहीं कर सकते हैं और फिर उसे कॉलम से बांध सकते हैं? जैसा कि आप एक सूची बॉक्स के लिए करेंगे। – deanvmc

+0

यह लिंक: http://www.codeproject.com/KB/WPF/WPFDataGridExamples.aspx#templates में स्तंभ टेम्पलेट का उपयोग करके वास्तविक स्तंभों को स्टाइल करने पर अधिक है, यह पृष्ठ के आधे रास्ते के नीचे है। – deanvmc

-5

डेटाग्रिडटेक्स्ट कॉलम इसमें टेक्स्टब्लॉक वाला कॉलम नहीं है। TargetType के साथ टेक्स्टब्लॉक के रूप में एक शैली लिखें और डेटाग्रिडटेक्स्ट कॉलम की एलिमेंट स्टाइल संपत्ति को बाध्य करें। उम्मीद है की वो मदद करदे!

+0

टेक्स्टब्लॉक एक सिस्टम नहीं है। 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

शैली टैग सही जगह में जाना पड़ता है। आपका datagrid अब इस अधिकार की तरह कुछ लग सकता है:

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

आप शुरू में DataGridTextColumn तत्व है जो काम नहीं करेगा भीतर सीधे शैली टैग को जोड़ने के लिए कोशिश कर सकते हैं। हालांकि आप "DataGridTextColumn.ElementStyle" और "DataGridTextColumn.EditingElementStyle" के लिए केवल "DataGridTextColumn" तत्व के भीतर तत्व बना सकते हैं।उन तत्व टैग से प्रत्येक फिर उन्हें भीतर शैली टैग नहीं है कर सकते हैं:

<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> 

एक शैली को देखने के लिए लागू किया जाएगा और जब सेल संपादन मोड में है अन्य लागू किया जाएगा। ध्यान दें कि संपादन करते समय टेक्स्टबॉक्स पर देखते समय यह टेक्स्टब्लॉक से बदलता है (यह मुझे पहले मिला है!)।

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> 
संबंधित मुद्दे