2009-07-28 18 views
265

मेरे पास WPF में TextBlock है। मैं इसके लिए कई रेखाएं लिखता हूं, इसकी ऊर्ध्वाधर ऊंचाई से कहीं अधिक है। जब ऐसा होता है तो मुझे स्वचालित रूप से एक लंबवत स्क्रॉल बार दिखाई देने की उम्मीद थी, लेकिन ऐसा नहीं हुआ। मैंने प्रॉपर्टी फलक में स्क्रॉल बार प्रॉपर्टी देखने की कोशिश की, लेकिन एक नहीं मिला।डब्ल्यूपीएफ टेक्स्टब्लॉक में स्वचालित वर्टिकल स्क्रॉल बार?

मेरी सामग्री अपनी ऊंचाई से अधिक होने के बाद मैं अपने TextBlock के लिए स्वचालित रूप से वर्टिकल स्क्रॉल बार कैसे बना सकता हूं?

स्पष्टीकरण: मैं इसे डिजाइनर से ही करूंगा, न कि सीधे XAML को लिखकर।

+0

इस प्रश्न को दोबारा पढ़ने पर, मुझे लगता है कि आप एक बार 'टेक्स्टब्लॉक'' और 'टेक्स्टबॉक्स' का उल्लेख करते हैं। –

उत्तर

446

एक स्क्रॉल दर्शक में यह लपेटें:

<ScrollViewer> 
    <TextBlock /> 
</ScrollViewer> 

नोट इस जवाब एक TextBlock (केवल पढ़ने के लिए पाठ तत्व) पर लागू होता है के रूप में मूल प्रश्न में के लिए कहा।

<TextBox ScrollViewer.HorizontalScrollBarVisibility="Disabled" 
     ScrollViewer.VerticalScrollBarVisibility="Auto" /> 

इन दो गुणों के लिए मान्य मान Disabled, Auto, Hidden और Visible हैं:

आप एक TextBox (एक संपादन योग्य पाठ तत्व) में स्क्रॉल बार दिखाने के लिए तो चाहते हैं ScrollViewer संलग्न गुण का उपयोग करें।

<TextBox Name="myTextBox" 
     ScrollViewer.HorizontalScrollBarVisibility="Auto" 
     ScrollViewer.VerticalScrollBarVisibility="Auto" 
     ScrollViewer.CanContentScroll="True">SOME TEXT 
</TextBox> 
+2

मैं इसे डिजाइनर से कैसे करूं? –

+14

क्षमा करें मुझे यकीन नहीं है, मैं WPF डिजाइनर का उपयोग नहीं करता हूं। मुझे लगता है कि अगर आप सीधे एक्सएएमएल जोड़ते हैं, तो डिजाइनर खुद को अपडेट करेगा। –

+5

@conqenator TextBox.ScrollToEnd(); –

89

अब निम्न का उपयोग कर सकते यदि आप ग्रिड का उपयोग नहीं करते हैं तो मामला बनें। यह तब हुआ जब मैंने अन्य समाधानों की कोशिश की, भले ही टेक्स्टब्लॉक पहले से ही अन्य तत्वों के साथ ग्रिड में था। ध्यान रखें कि टेक्स्टब्लॉक की चौड़ाई ऑटो होनी चाहिए और आपको ग्रिड तत्व में वांछित निर्दिष्ट करना चाहिए। मैंने यह मेरे कोड में किया और यह खूबसूरती से काम करता है। एचटीएच।

+3

धन्यवाद! यह उपरोक्त उत्तर से बेहतर मेरे लिए काम किया। – jjnguy

+14

@jjnguy, मैंने मूल प्रश्न का अर्थ 'टेक्स्टब्लॉक' के रूप में 'टेक्स्टबॉक्स' (शीर्षक और खोलने वाली रेखा के रूप में) के रूप में किया है, लेकिन दूसरा अनुच्छेद 'टेक्स्टबॉक्स' का उल्लेख करता है। स्पष्ट होने के लिए, यह उत्तर टेक्स्ट _boxes_ के लिए निश्चित रूप से सबसे अच्छा तरीका है, और मेरा सबसे अच्छा टेक्स्ट _blocks_ के लिए मुझे पता है :) –

+0

@ ड्रू, आह, समझ में आता है। स्पष्टीकरण के लिए धन्यवाद। – jjnguy

18

कुछ बेहतर होगा:

<Grid Width="Your-specified-value" > 
    <ScrollViewer> 
     <TextBlock Width="Auto" TextWrapping="Wrap" /> 
    </ScrollViewer> 
</Grid> 

यह सुनिश्चित करें कि आपके TextBlock में पाठ अतिप्रवाह नहीं करता है और हो सकता है के रूप में TextBlock नीचे तत्वों ओवरलैप बनाता

4
<ScrollViewer Height="239" VerticalScrollBarVisibility="Auto"> 
    <TextBox AcceptsReturn="True" TextWrapping="Wrap" LineHeight="10" /> 
</ScrollViewer> 

यह XAML में स्क्रॉलिंग टेक्स्टबॉक्स का उपयोग करने और टेक्स्ट क्षेत्र के रूप में उपयोग करने का तरीका है।

+1

प्रश्न 'टेक्स्टब्लॉक' से संबंधित है 'टेक्स्टबॉक्स' नहीं। –

+0

काफी सही उत्तर नहीं है, लेकिन मुझे वर्टिकलस्क्रोलबार दृश्यता एक उपयोगी संकेत होने के लिए मिली है, इसलिए +1 – Malachi

3

इस उत्तर के लिए एक समाधान MVVM का उपयोग कर का वर्णन है।

यह समाधान बहुत अच्छा है यदि आप किसी विंडो में लॉगिंग बॉक्स जोड़ना चाहते हैं, जो प्रत्येक बार एक नया लॉगिंग संदेश जोड़ा जाता है, तो स्वचालित रूप से नीचे स्क्रॉल करता है।

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

public static class TextBoxClearBehavior 
{ 
    public static readonly DependencyProperty TextBoxClearProperty = 
     DependencyProperty.RegisterAttached(
      "TextBoxClear", 
      typeof(bool), 
      typeof(TextBoxClearBehavior), 
      new UIPropertyMetadata(false, OnTextBoxClearPropertyChanged)); 

    public static bool GetTextBoxClear(DependencyObject obj) 
    { 
     return (bool)obj.GetValue(TextBoxClearProperty); 
    } 

    public static void SetTextBoxClear(DependencyObject obj, bool value) 
    { 
     obj.SetValue(TextBoxClearProperty, value); 
    } 

    private static void OnTextBoxClearPropertyChanged(
     DependencyObject d, 
     DependencyPropertyChangedEventArgs args) 
    { 
     if ((bool)args.NewValue == false) 
     { 
      return; 
     } 

     var textBox = (TextBox)d; 
     textBox?.Clear(); 
    } 
} 

यदि आप ':

<TextBox IsReadOnly="True" 
     Foreground="Gainsboro"       
     FontSize="13" 
     ScrollViewer.HorizontalScrollBarVisibility="Auto" 
     ScrollViewer.VerticalScrollBarVisibility="Auto" 
     ScrollViewer.CanContentScroll="True" 
     attachedBehaviors:TextBoxApppendBehaviors.AppendText="{Binding LogBoxViewModel.AttachedPropertyAppend}"          
     attachedBehaviors:TextBoxClearBehavior.TextBoxClear="{Binding LogBoxViewModel.AttachedPropertyClear}"          
     TextWrapping="Wrap"> 

इस जुड़ी संपत्ति जोड़ें:: (बॉक्स को साफ़ करने के लिए)

public static class TextBoxApppendBehaviors 
{ 
    #region AppendText Attached Property 
    public static readonly DependencyProperty AppendTextProperty = 
     DependencyProperty.RegisterAttached(
      "AppendText", 
      typeof (string), 
      typeof (TextBoxApppendBehaviors), 
      new UIPropertyMetadata(null, OnAppendTextChanged)); 

    public static string GetAppendText(TextBox textBox) 
    { 
     return (string)textBox.GetValue(AppendTextProperty); 
    } 

    public static void SetAppendText(
     TextBox textBox, 
     string value) 
    { 
     textBox.SetValue(AppendTextProperty, value); 
    } 

    private static void OnAppendTextChanged(
     DependencyObject d, 
     DependencyPropertyChangedEventArgs args) 
    { 
     if (args.NewValue == null) 
     { 
      return; 
     } 

     string toAppend = args.NewValue.ToString(); 

     if (toAppend == "") 
     { 
      return; 
     } 

     TextBox textBox = d as TextBox; 
     textBox?.AppendText(toAppend); 
     textBox?.ScrollToEnd(); 
    } 
    #endregion 
} 

और यह संलग्न संपत्ति

इस XAML जोड़े एमईएफ जैसे निर्भरता इंजेक्शन ढांचे का उपयोग कर फिर से, आप लॉगिंग-विशिष्ट कोड को अपने स्वयं के व्यू मॉडेल में रख सकते हैं:

public interface ILogBoxViewModel 
{ 
    void CmdAppend(string toAppend); 
    void CmdClear(); 

    bool AttachedPropertyClear { get; set; } 

    string AttachedPropertyAppend { get; set; } 
} 

[Export(typeof(ILogBoxViewModel))] 
public class LogBoxViewModel : ILogBoxViewModel, INotifyPropertyChanged 
{ 
    private readonly ILog _log = LogManager.GetLogger<LogBoxViewModel>(); 

    private bool _attachedPropertyClear; 
    private string _attachedPropertyAppend; 

    public void CmdAppend(string toAppend) 
    { 
     string toLog = $"{DateTime.Now:HH:mm:ss} - {toAppend}\n"; 

     // Attached properties only fire on a change. This means it will still work if we publish the same message twice. 
     AttachedPropertyAppend = ""; 
     AttachedPropertyAppend = toLog; 

     _log.Info($"Appended to log box: {toAppend}."); 
    } 

    public void CmdClear() 
    { 
     AttachedPropertyClear = false; 
     AttachedPropertyClear = true; 

     _log.Info($"Cleared the GUI log box."); 
    } 

    public bool AttachedPropertyClear 
    { 
     get { return _attachedPropertyClear; } 
     set { _attachedPropertyClear = value; OnPropertyChanged(); } 
    } 

    public string AttachedPropertyAppend 
    { 
     get { return _attachedPropertyAppend; } 
     set { _attachedPropertyAppend = value; OnPropertyChanged(); } 
    } 

    #region INotifyPropertyChanged 
    public event PropertyChangedEventHandler PropertyChanged; 

    [NotifyPropertyChangedInvocator] 
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
    } 
    #endregion 
} 

यहाँ यह कैसे काम करता है:

  • ViewModel संलग्न गुण पाठ बॉक्स नियंत्रित करने के लिए टॉगल करता है।
  • चूंकि यह "परिशिष्ट" का उपयोग कर रहा है, यह बिजली तेज है।
  • कोई अन्य व्यूमोडेल लॉगिंग व्यूमोडेल पर विधियों को कॉल करके लॉगिंग संदेश उत्पन्न कर सकता है।
  • जैसा कि हम टेक्स्टबॉक्स में बनाए गए स्क्रॉलव्यूयर का उपयोग करते हैं, हम प्रत्येक बार एक नया संदेश जोड़ते समय इसे स्वचालित रूप से टेक्स्टबॉक्स के नीचे स्क्रॉल कर सकते हैं।
3
<ScrollViewer MaxHeight="50" 
       Width="Auto" 
       HorizontalScrollBarVisibility="Disabled" 
       VerticalScrollBarVisibility="Auto"> 
    <TextBlock Text="{Binding Path=}" 
       Style="{StaticResource TextStyle_Data}" 
       TextWrapping="Wrap" /> 
</ScrollViewer> 

मैं ScrollViewer में maxHeight रख कर किसी अन्य तरीके से यह कर रहा हूं।

बस टेक्स्ट की अधिक या कम पंक्तियां दिखाने के लिए मैक्सहेइट समायोजित करें। आसान।