첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
------------------------------------------------------------------------------------------------------------------------------------------------------
728x90
728x170

TestProject.zip
0.03MB

▶ Recipe.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;

namespace TestProject
{
    /// <summary>
    /// 레시피
    /// </summary>
    public class Recipe
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Property
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 번호 - Number

        /// <summary>
        /// 번호
        /// </summary>
        public int Number { get; set; }

        #endregion
        #region 명칭 - Name

        /// <summary>
        /// 명칭
        /// </summary>
        public string Name { get; set; }

        #endregion
        #region 색상 - Color

        /// <summary>
        /// 색상
        /// </summary>
        public string Color { get; set; }

        #endregion
        #region 재료 리스트 - IngrdientList

        /// <summary>
        /// 재료 리스트
        /// </summary>
        public List<string> IngrdientList { get; set; }

        #endregion
        #region 재료 리스트 - Ingredients

        /// <summary>
        /// 재료 리스트
        /// </summary>
        public string Ingredients { get; set; }

        #endregion
        #region 재료 수 - IngredientCount

        /// <summary>
        /// 재료 수
        /// </summary>
        public int IngredientCount
        {
            get 
            {
                return IngrdientList.Count();
            }
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 재료 임의로 추가하기 - RandomizeIngredients()

        /// <summary>
        /// 재료 임의로 추가하기
        /// </summary>
        public void RandomizeIngredients()
        {
            Random numberRandom     = new Random();
            Random ingredientRandom = new Random();

            ObservableCollection<string> collection = new ObservableCollection<string>
            {
                "Garlic",
                "Lemon",
                "Butter",
                "Lime",
                "Feta Cheese",
                "Parmesan Cheese",
                "Breadcrumbs"
            };

            for(int i = 0; i < numberRandom.Next(0,4); i++)
            {
                string newIngredient = collection[ingredientRandom.Next(0, 6)];

                if(!IngrdientList.Contains(newIngredient))
                {
                    Ingredients += "\n" + newIngredient;

                    IngrdientList.Add(newIngredient);
                }
            }
        }

        #endregion
    }
}

 

728x90

 

▶ RecipeList.cs

using Microsoft.UI.Xaml.Controls;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;

namespace TestProject
{
    /// <summary>
    /// 레시피 리스트
    /// </summary>
    public class RecipeList : IList, IKeyIndexMapping, INotifyCollectionChanged
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Event
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 컬렉션 변경시 - CollectionChanged

        /// <summary>
        /// 컬렉션 변경시
        /// </summary>
        public event NotifyCollectionChangedEventHandler CollectionChanged;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 내부 리스트
        /// </summary>
        private List<Recipe> innerList = new List<Recipe>();

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region (IList) 카운트 - Count

        /// <summary>
        /// 카운트
        /// </summary>
        public int Count => this.innerList != null ? this.innerList.Count : 0;

        #endregion
        #region (IList) 인덱서 - this[index]

        /// <summary>
        /// 인덱서
        /// </summary>
        /// <param name="index">인덱스</param>
        /// <returns>레시피</returns>
        public object this[int index]
        {
            get
            {
                return this.innerList[index] as Recipe;
            }

            set
            {
                this.innerList[index] = (Recipe)value;
            }
        }

        #endregion

        #region (IList) 고정 크기 여부 - IsFixedSize

        /// <summary>
        /// 고정 크기 여부
        /// </summary>
        public bool IsFixedSize => throw new NotImplementedException();

        #endregion
        #region (IList) 읽기 전용 여부 - IsReadOnly

        /// <summary>
        /// 읽기 전용 여부
        /// </summary>
        public bool IsReadOnly => throw new NotImplementedException();

        #endregion
        #region (IList) 동기화 여부 - IsSynchronized

        /// <summary>
        /// 동기화 여부
        /// </summary>
        public bool IsSynchronized => throw new NotImplementedException();

        #endregion
        #region (IList) 동기 루트 - SyncRoot

        /// <summary>
        /// 동기 루트
        /// </summary>
        public object SyncRoot => throw new NotImplementedException();

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - RecipeList(recipeEnumerable)

        /// <summary>
        /// 생성자
        /// </summary>
        /// <param name="recipeEnumerable">레시피 열거 가능형</param>
        public RecipeList(IEnumerable<Recipe> recipeEnumerable)
        {
            InitializeCollection(recipeEnumerable);
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 컬렉션 초기화하기 - InitializeCollection(recipeEnumerable)

        /// <summary>
        /// 컬렉션 초기화하기
        /// </summary>
        /// <param name="recipeEnumerable">레시피 열거 가능형</param>
        public void InitializeCollection(IEnumerable<Recipe> recipeEnumerable)
        {
            this.innerList.Clear();

            if(recipeEnumerable != null)
            {
                this.innerList.AddRange(recipeEnumerable);
            }

            CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }

        #endregion

        #region (IList) 열거자 구하기 - GetEnumerator()

        /// <summary>
        /// 열거자 구하기
        /// </summary>
        /// <returns>열거자</returns>
        public IEnumerator<Recipe> GetEnumerator() => this.innerList.GetEnumerator();

        #endregion
        #region (IList) 열거자 구하기 - IEnumerable.GetEnumerator()

        /// <summary>
        /// 열거자 구하기
        /// </summary>
        /// <returns>열거자</returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            throw new NotImplementedException();
        }

        #endregion
        #region (IList) 추가하기 - Add(value)

        /// <summary>
        /// 추가하기
        /// </summary>
        /// <param name="value">값</param>
        /// <returns>인덱스</returns>
        public int Add(object value)
        {
            throw new NotImplementedException();
        }

        #endregion
        #region (IList) 지우기 - Clear()

        /// <summary>
        /// 지우기
        /// </summary>
        public void Clear()
        {
            throw new NotImplementedException();
        }

        #endregion
        #region (IList) 포함 여부 구하기 - Contains(value)

        /// <summary>
        /// 포함 여부 구하기
        /// </summary>
        /// <param name="value">값</param>
        /// <returns>포함 여부</returns>
        public bool Contains(object value)
        {
            throw new NotImplementedException();
        }

        #endregion
        #region (IList) 인덱스 구하기 - IndexOf(value)

        /// <summary>
        /// 인덱스 구하기
        /// </summary>
        /// <param name="value">값</param>
        /// <returns>인덱스</returns>
        public int IndexOf(object value)
        {
            throw new NotImplementedException();
        }

        #endregion
        #region (IList) 삽입하기 - Insert(index, value)

        /// <summary>
        /// 삽입하기
        /// </summary>
        /// <param name="index">인덱스</param>
        /// <param name="value">값</param>
        public void Insert(int index, object value)
        {
            throw new NotImplementedException();
        }

        #endregion
        #region (IList) 제거하기 - Remove(value)

        /// <summary>
        /// 제거하기
        /// </summary>
        /// <param name="value">값</param>
        public void Remove(object value)
        {
            throw new NotImplementedException();
        }

        #endregion
        #region (IList) 제거하기 - RemoveAt(index)

        /// <summary>
        /// 제거하기
        /// </summary>
        /// <param name="index">인덱스</param>
        public void RemoveAt(int index)
        {
            throw new NotImplementedException();
        }

        #endregion
        #region (IList) 복사하기 - CopyTo(array, index)

        /// <summary>
        /// 복사하기
        /// </summary>
        /// <param name="array">배열</param>
        /// <param name="index">인덱스</param>
        public void CopyTo(Array array, int index)
        {
            throw new NotImplementedException();
        }

        #endregion

        #region (IKeyIndexMapping) 인덱스에서 키 구하기 - KeyFromIndex(index)

        /// <summary>
        /// 인덱스에서 키 구하기
        /// </summary>
        /// <param name="index">인덱스</param>
        /// <returns>키</returns>
        public string KeyFromIndex(int index)
        {
            return this.innerList[index].Number.ToString();
        }

        #endregion
        #region (IKeyIndexMapping) 키에서 인덱스 구하기 - IndexFromKey(key)

        /// <summary>
        /// 키에서 인덱스 구하기
        /// </summary>
        /// <param name="key">키</param>
        /// <returns>인덱스</returns>
        public int IndexFromKey(string key)
        {
           foreach(Recipe recipe in this.innerList)
           {
                if(recipe.Number.ToString() == key)
                {
                    return this.innerList.IndexOf(recipe);
                }
           }

           return -1;
        }

        #endregion
    }
}

 

300x250

 

▶ CustomVirtualizingLayout.cs

using Microsoft.UI.Xaml.Controls;
using System.Collections.Generic;
using System.Collections.Specialized;
using Windows.Foundation;
using Windows.UI.Xaml;

namespace TestProject
{
    /// <summary>
    /// 커스텀 가상화 레이아웃
    /// </summary>
    public class CustomVirtualizingLayout : VirtualizingLayout
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 첫번쨰 인덱스
        /// </summary>
        private int firstIndex = 0;

        /// <summary>
        /// 마지막 인덱스
        /// </summary>
        private int lastIndex = 0;

        /// <summary>
        /// 마지막 이용 가능한 너비
        /// </summary>
        private double lastAvailableWidth = 0.0;

        /// <summary>
        /// 컬럼 오프셋 리스트
        /// </summary>
        private List<double> columnOffsetList = new List<double>();

        /// <summary>
        /// 캐시 테두리 사각형 리스트
        /// </summary>
        private List<Rect> cachedBoundRectangleList = new List<Rect>();

        /// <summary>
        /// 캐시 테두리 사각형 무효화 여부
        /// </summary>
        private bool cachedBoundRectangleInvalid = false;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 너비 - Width

        /// <summary>
        /// 너비
        /// </summary>
        public double Width { get; set; } = 150;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Protected

        #region 항목 변경시 처리하기 (코어) - OnItemsChangedCore(context, source, e)

        /// <summary>
        /// 항목 변경시 처리하기 (코어)
        /// </summary>
        /// <param name="context">컨텍스트</param>
        /// <param name="source">소스</param>
        /// <param name="e">이벤트 인자</param>
        protected override void OnItemsChangedCore(VirtualizingLayoutContext context, object source, NotifyCollectionChangedEventArgs e)
        {
            this.cachedBoundRectangleList.Clear();

            this.firstIndex = this.lastIndex = 0;

            this.cachedBoundRectangleInvalid = true;

            InvalidateMeasure();
        }

        #endregion
        #region 측정하기 (오버라이드) - MeasureOverride(context, availableSize)

        /// <summary>
        /// 측정하기 (오버라이드)
        /// </summary>
        /// <param name="context">컨텍스트</param>
        /// <param name="availableSize">이용 가능한 크기</param>
        /// <returns>측정 크기</returns>
        protected override Size MeasureOverride(VirtualizingLayoutContext context, Size availableSize)
        {
            Rect viewportRectangle = context.RealizationRect;

            if(availableSize.Width != this.lastAvailableWidth || this.cachedBoundRectangleInvalid)
            {
                UpdateCachedBoundRectangle(availableSize);

                this.lastAvailableWidth = availableSize.Width;
            }

            int columnCount = (int)(availableSize.Width / Width);

            if(this.columnOffsetList.Count == 0)
            {
                for(int i = 0; i < columnCount; i++)
                {
                    this.columnOffsetList.Add(0);
                }
            }

            this.firstIndex = GetStartIndex(viewportRectangle);

            int currentIndex = this.firstIndex;

            double nextOffset = -1.0;

            while(currentIndex < context.ItemCount && nextOffset < viewportRectangle.Bottom)
            {
                UIElement childElement = context.GetOrCreateElementAt(currentIndex);

                childElement.Measure(new Size(Width, availableSize.Height));

                if(currentIndex >= this.cachedBoundRectangleList.Count)
                {
                    int columnIndex = GetIndexOfLowestColumn(this.columnOffsetList, out nextOffset);

                    this.cachedBoundRectangleList.Add
                    (
                        new Rect
                        (
                            columnIndex * Width,
                            nextOffset,
                            Width,
                            childElement.DesiredSize.Height
                        )
                    );

                    this.columnOffsetList[columnIndex] += childElement.DesiredSize.Height;
                }
                else
                {
                    if(currentIndex + 1 == this.cachedBoundRectangleList.Count)
                    {
                        GetIndexOfLowestColumn(this.columnOffsetList, out nextOffset);
                    }
                    else
                    {
                        nextOffset = this.cachedBoundRectangleList[currentIndex + 1].Top;
                    }
                }

                this.lastIndex = currentIndex;

                currentIndex++;
            }

            Size extentSize = GetExtentSize(availableSize);

            return extentSize;
        }

        #endregion
        #region 배열하기 (오버라이드) - ArrangeOverride(context, finalSize)

        /// <summary>
        /// 배열하기 (오버라이드)
        /// </summary>
        /// <param name="context">컨텍스트</param>
        /// <param name="finalSize">최종 크기</param>
        /// <returns>배열 크기</returns>
        protected override Size ArrangeOverride(VirtualizingLayoutContext context, Size finalSize)
        {
            if(this.cachedBoundRectangleList.Count > 0)
            {
                for(int index = this.firstIndex; index <= this.lastIndex; index++)
                {
                    UIElement childElement = context.GetOrCreateElementAt(index);

                    childElement.Arrange(this.cachedBoundRectangleList[index]);
                }
            }

            return finalSize;
        }

        #endregion

        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region 캐시 테두리 사각형 업데이트하기 - UpdateCachedBoundRectangle(availableSize)

        /// <summary>
        /// 캐시 테두리 사각형 업데이트하기
        /// </summary>
        /// <param name="availableSize">이용 가능한 크기</param>
        private void UpdateCachedBoundRectangle(Size availableSize)
        {
            int columnCount = (int)(availableSize.Width / Width);

            this.columnOffsetList.Clear();

            for(int i = 0; i < columnCount; i++)
            {
                this.columnOffsetList.Add(0);
            }

            for(int index = 0; index < this.cachedBoundRectangleList.Count; index++)
            {
                int columnIndex = GetIndexOfLowestColumn(this.columnOffsetList, out var nextOffset);

                double previousHeight = this.cachedBoundRectangleList[index].Height;

                this.cachedBoundRectangleList[index] = new Rect(columnIndex * Width, nextOffset, Width, previousHeight);

                this.columnOffsetList[columnIndex] += previousHeight;
            }

            this.cachedBoundRectangleInvalid = false;
        }

        #endregion
        #region 시작 인덱스 구하기 - GetStartIndex(viewportRectangle)

        /// <summary>
        /// 시작 인덱스 구하기
        /// </summary>
        /// <param name="viewportRectangle">뷰포트 사각형</param>
        /// <returns>시작 인덱스</returns>
        private int GetStartIndex(Rect viewportRectangle)
        {
            int startIndex = 0;

            if(this.cachedBoundRectangleList.Count == 0)
            {
                startIndex = 0;
            }
            else
            {
                for(int i = 0; i < this.cachedBoundRectangleList.Count; i++)
                {
                    Rect currentBoundRectangle = this.cachedBoundRectangleList[i];

                    if(currentBoundRectangle.Y < viewportRectangle.Bottom && currentBoundRectangle.Bottom > viewportRectangle.Top)
                    {
                        startIndex = i;

                        break;
                    }
                }
            }

            return startIndex;
        }

        #endregion
        #region 가장 낮은 컬럼 인덱스 구하기 - GetIndexOfLowestColumn(columnOffsetList, lowestOffset)

        /// <summary>
        /// 가장 낮은 컬럼 인덱스 구하기
        /// </summary>
        /// <param name="columnOffsetList">컬럼 오프셋 리스트</param>
        /// <param name="lowestOffset">가장 낮은 오프셋</param>
        /// <returns>가장 낮은 컬럼 인덱스</returns>
        private int GetIndexOfLowestColumn(List<double> columnOffsetList, out double lowestOffset)
        {
            int lowestIndex = 0;

            lowestOffset = columnOffsetList[lowestIndex];

            for(int index = 0; index < columnOffsetList.Count; index++)
            {
                double currentOffset = columnOffsetList[index];

                if(lowestOffset > currentOffset)
                {
                    lowestOffset = currentOffset;

                    lowestIndex = index;
                }
            }

            return lowestIndex;
        }

        #endregion
        #region 범위 크기 구하기 - GetExtentSize(availableSize)

        /// <summary>
        /// 범위 크기 구하기
        /// </summary>
        /// <param name="availableSize">이용 가능한 크기</param>
        /// <returns>범위 크기</returns>
        private Size GetExtentSize(Size availableSize)
        {
            double largestColumnOffset = this.columnOffsetList[0];

            for(int index = 0; index < this.columnOffsetList.Count; index++)
            {
                double currentOffset = this.columnOffsetList[index];

                if(largestColumnOffset < currentOffset)
                {
                    largestColumnOffset = currentOffset;
                }
            }

            return new Size(availableSize.Width, largestColumnOffset);
        }

        #endregion
    }
}

 

▶ MainPage.xaml

<Page x:Class="TestProject.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
    xmlns:local="using:TestProject"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
    FontFamily="나눔고딕코딩"
    FontSize="16">
    <Page.Resources>
        <DataTemplate x:Key="RecipeDataTemplateKey" x:DataType="local:Recipe">
            <StackPanel
                Margin="5"
                BorderThickness="1"
                Background="{ThemeResource SystemControlBackgroundBaseLowBrush}">
                <StackPanel
                    Margin="10"
                    Height="75"
                    Background="{x:Bind Color}"
                    Opacity="0.8">
                    <TextBlock
                        Padding="10"
                        Foreground="{ThemeResource SystemControlForegroundAltHighBrush}"
                        FontSize="35"
                        TextAlignment="Center" 
                        Text="{x:Bind Number.ToString()}" />
                </StackPanel>
                <TextBlock
                    Style="{StaticResource TitleTextBlockStyle}"
                    Margin="15 0 10 0" 
                    TextWrapping="Wrap"
                    Text="{x:Bind Name}" />
                <TextBlock
                    Style="{StaticResource BodyTextBlockStyle}"
                    Margin="15 0 15 15"
                    Text="{x:Bind Ingredients}" />
            </StackPanel>
        </DataTemplate>
    </Page.Resources>
    <Grid>
        <Grid
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Margin="10">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"    />
                <ColumnDefinition Width="50"   />
                <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>
            <muxc:ItemsRepeaterScrollHost Grid.Column="0">
                <ScrollViewer>
                    <muxc:ItemsRepeater Name="itemsRepeater"
                        ItemTemplate="{StaticResource RecipeDataTemplateKey}">
                        <muxc:ItemsRepeater.Layout>
                            <local:CustomVirtualizingLayout Width="200" />
                        </muxc:ItemsRepeater.Layout>
                    </muxc:ItemsRepeater>
                </ScrollViewer>
            </muxc:ItemsRepeaterScrollHost>
            <StackPanel Grid.Column="2"
                Spacing="10">
                <TextBox x:Name="filerTextBox"
                    HorizontalAlignment="Left"
                    Width="200"
                    Header="재료 필터..."
                    TextChanged="filterTextBox_TextChanged"/>
                <TextBlock Text="애니메이션 사용" />
                <CheckBox Name="enableAnimationCheckBox"
                    Content="애니메이션 이용 가능 여부"
                    Checked="enableAnimationCheckBox_Checked" 
                    Unchecked="enableAnimationCheckBox_Checked" />
                <TextBlock Text="재료 수로 정렬" />
                <Button
                    Content="최소에서 최대"
                    Click="sortAscendingButton_Click" />
                <Button
                    Content="최대에서 최소"
                    Click="OnSortDescendingClick" />
            </StackPanel>
        </Grid>
    </Grid>
</Page>

 

▶ MainPage.xaml.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
using Windows.Foundation;
using Windows.Graphics.Display;
using Windows.UI;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace TestProject
{
    /// <summary>
    /// 메인 페이지
    /// </summary>
    public sealed partial class MainPage : Page
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 소스 레시피 리스트
        /// </summary>
        private List<Recipe> sourceRecipeList;

        /// <summary>
        /// 필터 레시피 티르스
        /// </summary>
        private RecipeList filteredRecipeList = new RecipeList(null);

        /// <summary>
        /// 역순 정렬 여부
        /// </summary>
        private bool isSortDescending = false;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - MainPage()

        /// <summary>
        /// 생성자
        /// </summary>
        public MainPage()
        {
            InitializeComponent();

            #region 윈도우 크기를 설정한다.

            double width  = 800d;
            double height = 600d;

            double dpi = (double)DisplayInformation.GetForCurrentView().LogicalDpi;

            ApplicationView.PreferredLaunchWindowingMode = ApplicationViewWindowingMode.PreferredLaunchViewSize;

            Size windowSize = new Size(width * 96d / dpi, height * 96d / dpi);

            ApplicationView.PreferredLaunchViewSize = windowSize;

            Window.Current.Activate();

            ApplicationView.GetForCurrentView().TryResizeView(windowSize);

            #endregion
            #region 윈도우 제목을 설정한다.

            ApplicationView.GetForCurrentView().Title = "ItemsRepeater 엘리먼트 : 필터링/정렬 기능 사용하기";

            #endregion

            this.sourceRecipeList = GetRecipeList();

            this.filteredRecipeList.InitializeCollection(this.sourceRecipeList);

            this.itemsRepeater.ItemsSource = this.filteredRecipeList;
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Private
        //////////////////////////////////////////////////////////////////////////////// Event

        #region 재표 필터 텍스트 박스 텍스트 변경시 처리하기 - filterTextBox_TextChanged(sender, e)

        /// <summary>
        /// 재표 필터 텍스트 박스 텍스트 변경시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        public void filterTextBox_TextChanged(object sender, RoutedEventArgs e)
        {
            UpdateData();
        }

        #endregion
        #region 애니메이션 이용 가능 여부 체크 박스 체크시 처리하기 - enableAnimationCheckBox_Checked(sender, e)

        /// <summary>
        /// 애니메이션 이용 가능 여부 체크 박스 체크시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void enableAnimationCheckBox_Checked(object sender, RoutedEventArgs e)
        {
#if WINUI_PRERELEASE
             this.itemsRepeater.Animator = this.enableAnimationCheckBox.IsChecked.GetValueOrDefault() ? new DefaultElementAnimator() : null;
#endif
        }

        #endregion
        #region 최소에서 최대 버튼 클릭시 처리하기 - sortAscendingButton_Click(sender, e)

        /// <summary>
        /// 최소에서 최대 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void sortAscendingButton_Click(object sender, RoutedEventArgs e)
        {
            if(this.isSortDescending == true)
            {
                this.isSortDescending = false;

                UpdateData();
            }
        }

        #endregion
        #region 최대에서 최소 버튼 클릭시 처리하기 - OnSortDescendingClick(sender, e)

        /// <summary>
        /// 최대에서 최소 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void OnSortDescendingClick(object sender, RoutedEventArgs e)
        {
            if(!this.isSortDescending == true)
            {
                this.isSortDescending = true;

                UpdateData();
            }
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////// Function

        #region 과일 컬렉션 구하기 - GetFruitCollection()

        /// <summary>
        /// 과일 컬렉션 구하기
        /// </summary>
        /// <returns>과일 컬렉션</returns>
        private ObservableCollection<string> GetFruitCollection()
        {
            return new ObservableCollection<string> { "Apricots", "Bananas", "Grapes", "Strawberries", "Watermelon", "Plums", "Blueberries" };
        }

        #endregion
        #region 채소 컬렉션 구하기 - GetVegetableCollection()

        /// <summary>
        /// 채소 컬렉션 구하기
        /// </summary>
        /// <returns>채소 컬렉션</returns>
        private ObservableCollection<string> GetVegetableCollection()
        {
            return new ObservableCollection<string>{"Broccoli","Spinach","Sweet potato","Cauliflower","Onion", "Brussels sprouts","Carrots"};
        }

        #endregion
        #region 곡물 컬렉션 구하기 - GetGrainCollection()

        /// <summary>
        /// 곡물 컬렉션 구하기
        /// </summary>
        /// <returns>곡물 컬렉션</returns>
        private ObservableCollection<string> GetGrainCollection()
        {
            return new ObservableCollection<string>{"Rice", "Quinoa", "Pasta", "Bread", "Farro", "Oats", "Barley"};
        }

        #endregion
        #region 단백질 컬렉션 구하기 - GetProteinCollection()

        /// <summary>
        /// 단백질 컬렉션 구하기
        /// </summary>
        /// <returns>단백질 컬렉션</returns>
        private ObservableCollection<string> GetProteinCollection()
        {
            return new ObservableCollection<string>{"Steak", "Chicken", "Tofu", "Salmon", "Pork", "Chickpeas", "Eggs"};
        }

        #endregion
        #region 색상 리스트 구하기 - GetColorList()

        /// <summary>
        /// 색상 리스트 구하기
        /// </summary>
        /// <returns>색상 리스트</returns>
        private IList<string> GetColorList()
        {
            IList<string> list = (typeof(Colors).GetRuntimeProperties().Select(c => c.ToString())).ToList();

            for(int i = 0; i < list.Count(); i++)
            {
                list[i] = list[i].Substring(17);
            }

            return list;
        }

        #endregion
        #region 레시피 리스트 구하기 - GetRecipeList()

        /// <summary>
        /// 레시피 리스트 구하기
        /// </summary>
        /// <returns>레시피 리스트</returns>
        private List<Recipe> GetRecipeList()
        {
            Random random = new Random();

            IList<string> colorList = GetColorList();

            List<Recipe> list = new List<Recipe>
            (
                Enumerable.Range(0, 1000).Select
                (
                    index => new Recipe
                    {
                        Number = index,
                        Name   = "레시피 " + index.ToString(),
                        Color = colorList[(index % 100) + 1]
                    }
                )
            );

            ObservableCollection<string> fruitCollection     = GetFruitCollection();
            ObservableCollection<string> vegetableCollection = GetVegetableCollection();
            ObservableCollection<string> grainCollection     = GetGrainCollection();
            ObservableCollection<string> proteinCollection   = GetProteinCollection();

            foreach(Recipe recipe in list)
            {
                string fruit         = fruitCollection    [random.Next(0, 6)];
                string vegetable     = vegetableCollection[random.Next(0, 6)];
                string grain         = grainCollection    [random.Next(0, 6)];
                string protein       = proteinCollection  [random.Next(0, 6)];
                recipe.Ingredients   = "\n" + fruit + "\n" + vegetable + "\n" + grain + "\n" + protein;
                recipe.IngrdientList = new List<string>() { fruit, vegetable, grain, protein };

                recipe.RandomizeIngredients();
            }

            return list;
        }

        #endregion

        #region 데이터 업데이트하기 - UpdateData()

        /// <summary>
        /// 데이터 업데이트하기
        /// </summary>
        private void UpdateData()
        {
            var filteredRecipeEnumerable = this.sourceRecipeList.Where
            (
                ingredient => ingredient.Ingredients.Contains
                (
                    this.filerTextBox.Text,
                    StringComparison.InvariantCultureIgnoreCase
                )
            );

            var sortedRecipeEnumerable = this.isSortDescending ?
                filteredRecipeEnumerable.OrderByDescending(ingredient => ingredient.IngrdientList.Count()) :
                filteredRecipeEnumerable.OrderBy(ingredient => ingredient.IngrdientList.Count());

            this.filteredRecipeList.InitializeCollection(sortedRecipeEnumerable);
        }

        #endregion
    }
}
728x90
그리드형(광고전용)
Posted by icodebroker
,