รับตำแหน่งเลื่อนของกล่องข้อความ WPF

ฉันต้องเพิ่มการตกแต่งให้กับเนื้อหาของตัวควบคุมกล่องข้อความ WPF โดยพื้นฐานแล้วใช้งานได้ดี ฉันสามารถรับตำแหน่งของดัชนีอักขระที่ระบุและจัดวางองค์ประกอบอื่น ๆ ของฉันตามนั้น แต่ทุกอย่างจะพังเมื่อเลื่อนกล่องข้อความ ตำแหน่งเค้าโครงของฉันไม่ตรงกับข้อความที่แสดงอีกต่อไป เนื่องจากถูกย้ายไปที่อื่นแล้ว

ตอนนี้ฉันค่อนข้างแปลกใจที่คลาส TextBox ไม่ได้ให้ข้อมูลใด ๆ เกี่ยวกับสถานะการเลื่อนหรือเหตุการณ์ใด ๆ เมื่อการเลื่อนเปลี่ยนไป ฉันจะทำอย่างไรตอนนี้?

ฉันใช้ Snoop เพื่อดูว่ามีองค์ประกอบย่อยการเลื่อนบางอย่างที่ฉันสามารถถามได้หรือไม่ แต่ ScrollContentPresenter ยังไม่มีข้อมูลการเลื่อนใดๆ เลย ฉันอยากจะวางองค์ประกอบการตกแต่งของฉันลงในพื้นที่เลื่อนเพื่อให้การเลื่อนส่งผลต่อองค์ประกอบเหล่านั้นเช่นกัน แต่จะมีการควบคุมเนื้อหาได้เพียงส่วนเดียวเท่านั้นและนั่นก็เป็นหนึ่งในกล่องข้อความภายในอยู่แล้ว


person ygoe    schedule 15.02.2013    source แหล่งที่มา
comment
อาจลองสมัครรับเหตุการณ์กำหนดเส้นทาง ScrollViewer.ScrollChanged ไหม โดยให้ข้อมูลต่างๆ เช่น ความสูงของขอบเขต การเลื่อนออฟเซ็ต ขนาดวิวพอร์ต (ทั้งหมดเป็นขนาดแนวนอนและแนวตั้ง) บางทีมันอาจจะช่วยได้ ฉันไม่ค่อยแน่ใจว่าฉันเข้าใจงานของคุณอย่างสมบูรณ์ แต่ลองดูสิ   -  person Haspemulator    schedule 16.02.2013


คำตอบ (2)


ฉันไม่แน่ใจว่าจะจับภาพเหตุการณ์ได้อย่างไรเมื่อมีการเลื่อนกล่องข้อความ (อาจใช้คำตอบของ narohi สำหรับสิ่งนั้น) แต่มีวิธีง่ายๆ ในการดูว่าตำแหน่งการเลื่อนปัจจุบันคืออะไร:

// Gets or sets the vertical scroll position.
textBox.VerticalOffset

(จาก http://msdn.microsoft.com/en-us/library/system.windows.controls.primitives.textboxbase.verticaloffset(v=vs.100).aspx)

ฉันใช้มันเพื่อดูว่ากล่องข้อความถูกเลื่อนไปจนสุดหรือไม่ เช่นนี้

public static bool IsScrolledToEnd(this TextBox textBox)
{
    return textBox.VerticalOffset + textBox.ViewportHeight == textBox.ExtentHeight;
}
person John Gibb    schedule 05.02.2014
comment
จอห์น ขอบคุณ ฉันได้ลอง IsScrolledToEnd แล้ว มันมักจะได้ผล แต่ก็ไม่เสมอไป ปัญหาคือคุณกำลังเปรียบเทียบค่าสองเท่ากับตัวดำเนินการ == ฉันคิดว่าควรมีความอดทน 1 บรรทัดในการเปรียบเทียบนี้ เช่นนี้: bool scrollToEnd = Memo.VerticalOffset > Memo.ExtentHeight - Memo.ViewportHeight - fontHeight; - person Aleksandr; 12.12.2017
comment
@Aleksandr คุณได้รับ fontHeight ที่ไหน? ฉันใช้ Memo.FontSize และดูเหมือนว่าจะทำงานได้ตามที่ตั้งใจไว้ - person Gravitate; 19.03.2019
comment
double fontHeight = Memo.FontSize * Memo.FontFamily.LineSpacing; - person Aleksandr; 21.03.2019

คุณสามารถรับ ScrollViewer ด้วยวิธีนี้โดยส่งในกล่องข้อความของคุณเป็นอาร์กิวเมนต์และประเภท ScrollView จากนั้นคุณสามารถสมัครรับกิจกรรม ScrollChanged ได้

public static T FindDescendant<T>(DependencyObject obj) where T : DependencyObject
{
    if (obj == null) return default(T);
    int numberChildren = VisualTreeHelper.GetChildrenCount(obj);
    if (numberChildren == 0) return default(T);

    for (int i = 0; i < numberChildren; i++)
    {
        DependencyObject child = VisualTreeHelper.GetChild(obj, i);
        if (child is T)
        {
            return (T)(object)child;
        }
    }

    for (int i = 0; i < numberChildren; i++)
    {
        DependencyObject child = VisualTreeHelper.GetChild(obj, i);
        var potentialMatch = FindDescendant<T>(child);
        if (potentialMatch != default(T))
        {
            return potentialMatch;
        }
    }

    return default(T);
}

ตัวอย่าง:

public MainWindow()
{
    InitializeComponent();
    Loaded += new RoutedEventHandler(MainWindow_Loaded);
}

void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
    ScrollViewer s = FindDescendant<ScrollViewer>(txtYourTextBox);
    s.ScrollChanged += new ScrollChangedEventHandler(s_ScrollChanged);
}

void s_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
    // check event args for information needed
}
person Nathan Hillyer    schedule 15.02.2013