본문 바로가기

프로그래밍/C#, WPF, Winform

[WPF] ScrollViewer가 스크롤 할 때 보여지는 부분만 업데이트





한 화면에 Usercontrol을 화면을 넘치게 그리는 경우가 종종있다.

그럴 경우 ScrollViewer 컨트롤을 사용한다.

 

너무 많은 Usercontrol을 업데이트(먼가 힘든 작업)를 할 때 리소스를 많이 잡아 먹는다.

그래서 휴대폰 앱에서와 같이 스크롤된 부분만 그리는 작업이 필요하다.

 

화면에 보여지는 Usercontrol의 이벤트를 받아서 처리하면 먼가 깔끔하게 될거 같은데 현재로선 방법을 찾기힘들다.

그래서 대안으로 스크롤된 위치와 Usercontrol의 위치를 비교해서 처리하는 방식으로 구현을 했다. 

 

MainWindow.xaml

<Window x:Class="WpfApp3.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp3"
        mc:Ignorable="d"
        Title="MainWindow" Height="150" Width="210" Loaded="Window_Loaded" Grid.IsSharedSizeScope="True">
    <Grid>
        <ScrollViewer ScrollChanged="ScrollViewer_ScrollChanged" x:Name="scroll">
            <StackPanel x:Name="spMain" Orientation="Vertical" VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode ="Recycling">
                <local:UserControl1 x:Name="btnNum1" Margin="4 4 4 10" ID="1"/>
                <local:UserControl1 x:Name="btnNum2" Margin="4 4 4 10" ID="2"/>
                <local:UserControl1 x:Name="btnNum3" Margin="4 4 4 10" ID="3"/>
                <local:UserControl1 x:Name="btnNum4" Margin="4 4 4 10" ID="4"/>
                <local:UserControl1 x:Name="btnNum5" Margin="4 4 4 10" ID="5"/>
                <local:UserControl1 x:Name="btnNum6" Margin="4 4 4 10" ID="6"/>
            </StackPanel>
            
        </ScrollViewer>
    </Grid>
</Window>

 

MainWindows.cs

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApp3
{
    /// <summary>
    /// MainWindow.xaml에 대한 상호 작용 논리
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            foreach (UserControl1 item in spMain.Children)
            {
                GeneralTransform transform = item.TransformToAncestor(this);
                Point point = transform.Transform(new Point());
         
                if (point.Y < Height)
                {
                    item.DoSomthing();
                }
            }
        }

    }
}