티스토리 뷰

반응형

이번회 부터 게시물 목록을 작업 하도록 하겠다. 하지만, 이것도 조회, 추가 등 몇개로 나누어서 올릴 예정이다. 한번에 너무 만은 내용을 올리면 내용의 부담이 되어서 그런지..별로 좋아하지 않는 것같다.(아마도..ㅎㅎ)

이번회에는 모델, 뷰모델, 뷰를 만들고..(여기까지만 해도 소스 양은 상당하다..) 조회를 했을 때 그리드에 데이터 바인딩 하는 부분과 조회 조건 처리하는 방법, 연결된 데이터 조회(작성자명)하는 것들을 알아보도록 하고 시작 하기 전에 목표 화면을 보자~

심플한 화면~ 하하.. 역시나 기본적인 레이아웃은 실버라이트 코리아의 디자인을 카피 했다는..

1. Model

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.Linq;
using System.ServiceModel.DomainServices.Client;
using SL5_BOARD.Web.Model;

namespace SL5_BOARD.Models
{
    [Export(typeof(BoardList))]
    public class BoardList : INotifyPropertyChanged
    {
        #region PropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged(string PropertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
            }
        }
        #endregion

        /// <summary>
        /// Board 도메인 서비스 임포트
        /// </summary>
        [Import(typeof(BoardContext))]
        public BoardContext BoardDomainService { get; set; }

        [Import(typeof(MstMember))]
        public MstMember _mstMember { get; set; }

        ObservableCollection<BOARD_LIST> conditionData;
        /// <summary>
        /// 조건에 맞는 데이터
        /// </summary>
        public ObservableCollection<BOARD_LIST> ConditionData
        {
            get
            {
                return conditionData;
            }
            set
            {
                if (conditionData != value)
                {
                    conditionData = value;
                    OnPropertyChanged("ConditionData");
                }
            }
        }

        BOARD_LIST currentData;
        /// <summary>
        /// 현재 선택된 데이터
        /// </summary>
        public BOARD_LIST CurrentData
        {
            get
            {
                return currentData;
            }
            set
            {
                if (currentData != value)
                {
                    currentData = value;
                    OnPropertyChanged("CurrentData");
                }
            }
        }

        string messageData;
        /// <summary>
        /// 모델 메시지 데이터
        /// </summary>
        public string MessageData
        {
            get
            {
                return messageData;
            }
            private set
            {
                if (messageData != value)
                {
                    messageData = "[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "] " + value;
                    OnPropertyChanged("MessageData");
                }
            }
        }

        /// <summary>
        /// 생성자
        /// </summary>
        public BoardList()
        {
            ConditionData = new ObservableCollection<BOARD_LIST>();

            this.PropertyChanged += new PropertyChangedEventHandler(BoardList_PropertyChanged);
        }

        /// <summary>
        /// 프로퍼티 채인지 구현
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void BoardList_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            //모델 프로퍼티 체인지 이벤트 발생시 다른 프로퍼티에 영향을 줘야하는 경우사용
        }

        /// <summary>
        /// 조건 조회
        /// </summary>
        /// <param name="condition">조건</param>
        public void Getting(string condition)
        {
            if (condition.Length == 0)
            {
                //조건이 없을때는 모두 가지고 오는 함수 호출
                BoardDomainService.Context.Load(BoardDomainService.Context.GetBoardListQuery(),
                                                LoadBehavior.RefreshCurrent,
                                                load =>
                                                {
                                                    loadComplete(load);
                                                }, true);

            }
            else
            {
                //조건이 있으면 조건 조회 함수 호출
                BoardDomainService.Context.Load(BoardDomainService.Context.GetBoardListByConditionQuery(condition),
                                                LoadBehavior.RefreshCurrent,
                                                load =>
                                                {
                                                    loadComplete(load);
                                                }, true);
            }
        }

        /// <summary>
        /// Load 콜백 함수
        /// </summary>
        /// <param name="lo"></param>
        private void loadComplete(LoadOperation lo)
        {
            if (lo.HasError == false)
            {
                //조회 결과를 컨디션데이터로 만들고
                ConditionData = new ObservableCollection<BOARD_LIST>(lo.AllEntities.Cast<BOARD_LIST>());

                //컨디션데이터 중에 회원과 연결이 앙되어 있는 카운트를 구하고
                var count = (from list in ConditionData
                             where list.MstMember == null
                             select list).Count();

                //카운트가 0보다 크면 회원데이터를 조회한다.
                if (count > 0)
                {
                    _mstMember.Getting();
                }

                MessageData = "조회 작업을 완료 했습니다.";
            }
            else
            {
                MessageData = "조회 작업이 실패 했습니다.";
            }
        }

        /// <summary>
        /// 추가 함수
        /// </summary>
        /// <param name="addData">BOARD_LIST</param>
        public void Adding(Object addData)
        {
            if (addData != null && addData is BOARD_LIST)
            {
                BOARD_LIST item = addData as BOARD_LIST;
                item.REG_DT = DateTime.Now;
                item.REG_IDX = 1;
                BoardDomainService.Context.BOARD_LISTs.Add(item);
                CurrentData = item;

                MessageData = "추가 작업을 완료 했습니다.(저장을 해야 서버에 반영됩니다)";
            }
            else
            {
                MessageData = "데이터가 없거나 형식이 다릅니다.";
            }
        }
       
        /// <summary>
        /// 삭제 함수
        /// </summary>
        /// <param name="removeData">BOARD_LIST</param>
        public void Removing(Object removeData)
        {
            if (removeData != null && removeData is BOARD_LIST)
            {
                BoardDomainService.Context.BOARD_LISTs.Remove(removeData as BOARD_LIST);

                MessageData = "삭제 작업을 완료 했습니다.(저장을 해야 서버에 반영됩니다)";
            }
            else
            {
                MessageData = "데이터가 없거나 형식이 다릅니다.";
            }
        }

        /// <summary>
        /// 저장 함수
        /// </summary>
        public void Saving()
        {
            BoardDomainService.Context.SubmitChanges(submitCallBack, null);
        }

        /// <summary>
        /// 저장 콜백
        /// </summary>
        /// <param name="so"></param>
        private void submitCallBack(SubmitOperation so)
        {
            if (so.IsComplete == true)
            {
                MessageData = "저장 작업을 완료 했습니다.";
            }
            else
            {
                MessageData = "저장 작업을 실패 했습니다.";
            }
        }

        /// <summary>
        /// 취소 함수
        /// </summary>
        public void Canceling()
        {
            BoardDomainService.Context.RejectChanges();

            MessageData = "취소 작업을 완료 했습니다.";
        }

    }
}

2. ViewModel

using System.ComponentModel;
using System.ComponentModel.Composition;
using System.Windows.Input;
using Microsoft.Expression.Interactivity.Core;
using SL5_BOARD.Models;
using SL5_BOARD.Web.Model;
using System.Windows.Controls;

namespace SL5_BOARD.ViewModels
{
    [Export(typeof(BoardListViewModel))]
    public class BoardListViewModel : INotifyPropertyChanged
    {
        #region PropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged(string PropertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
            }
        }
        #endregion

        /// <summary>
        /// 보드리스트 임포트
        /// </summary>
        [Import(typeof(BoardList))]
        public BoardList BoardListData { get; set; }

        /// <summary>
        /// 생성자
        /// </summary>
        public BoardListViewModel()
        {
            this.PropertyChanged += new PropertyChangedEventHandler(BoardListViewModel_PropertyChanged);
        }

        /// <summary>
        /// 프로퍼티 체인지 이벤트 구현
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void BoardListViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            //로컬 프로퍼티 변경시 다른 프로퍼티에 영향을 미치는 경우 코딩
        }

        ICommand selectConditionCommand;
        /// <summary>
        /// 조건 조회 커맨드
        /// </summary>
        public ICommand SelectConditionCommand
        {
            get
            {
                if (selectConditionCommand == null)
                {
                    selectConditionCommand = new ActionCommand(condition =>
                    {
                        //조건을 가지는 조회 함수 실행
                        BoardListData.Getting(condition as string);
                    });
                }
                return selectConditionCommand;
            }
        }

        ICommand addCommand;
        /// <summary>
        /// 추가 커맨드
        /// </summary>
        public ICommand AddCommand
        {
            get
            {
                if (addCommand == null)
                {
                    addCommand = new ActionCommand(() =>
                    {
                        BOARD_LIST obj = new BOARD_LIST();
                        BoardListData.Adding(obj);
                    });
                }
                return addCommand;
            }
        }

        ICommand removeCommand;
        /// <summary>
        /// 삭제 커맨드
        /// </summary>
        public ICommand RemoveCommand
        {
            get
            {
                if (removeCommand == null)
                {
                    removeCommand = new ActionCommand(obj =>
                    {
                        if (obj != null && obj is BOARD_LIST)
                        {
                            BoardListData.Removing(obj);
                        }
                    });
                }
                return removeCommand;
            }
        }

        ICommand saveCommand;
        /// <summary>
        /// 저장 커맨드
        /// </summary>
        public ICommand SaveCommand
        {
            get
            {
                if (saveCommand == null)
                {
                    saveCommand = new ActionCommand(() =>
                    {
                        BoardListData.Saving();
                    });
                }
                return saveCommand;
            }
        }

        ICommand cancelCommand;
        /// <summary>
        /// 취소 커맨드
        /// </summary>
        public ICommand CancelCommand
        {
            get
            {
                if (cancelCommand == null)
                {
                    cancelCommand = new ActionCommand(() =>
                    {
                        BoardListData.Canceling();
                    });
                }
                return cancelCommand;
            }
        }

        ICommand selectChanged;
        /// <summary>
        /// 현재 아이템 변경 커맨드
        /// </summary>
        public ICommand SelectChangedCommand
        {
            get
            {
                if (selectChanged == null)
                {
                    selectChanged = new ActionCommand(obj => SelectChangedOperation(obj));
                }
                return selectChanged;
            }
        }

        private void SelectChangedOperation(object obj)
        {
            if (obj != null && obj is BOARD_LIST)
                BoardListData.CurrentData = obj as BOARD_LIST;
        }
    }
}

3. View

<UserControl
    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:SL5_BOARD_ViewModels="clr-namespace:SL5_BOARD.ViewModels"
 xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
 xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
 x:Class="SL5_BOARD.Views.BoardListView"
    mc:Ignorable="d"
    d:DesignHeight="500" d:DesignWidth="600">
   
 <Grid x:Name="LayoutRoot" Background="White">
  <Grid.RowDefinitions>
   <RowDefinition Height="38"/>
   <RowDefinition Height="35"/>
   <RowDefinition/>
   <RowDefinition Height="35"/>
  </Grid.RowDefinitions>

  <Grid.DataContext>
   <SL5_BOARD_ViewModels:BoardListViewModel/>
  </Grid.DataContext>

  <i:Interaction.Triggers>
   <i:EventTrigger>
    <i:InvokeCommandAction Command="{Binding SelectConditionCommand, Mode=OneWay}" CommandParameter="{Binding Text, ElementName=txtCondition}"/>
   </i:EventTrigger>
  </i:Interaction.Triggers>

  <!--메인 타이틀-->
  <TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="게시물 목록" FontSize="14.667" FontWeight="Bold" Foreground="{StaticResource ForeColor_Blues}" Margin="10,6,0,10" d:LayoutOverrides="Height"/>
  <!--Line-->
  <Path Data="M0,30 L400,30" Fill="#FF5181B9" Height="3" Margin="0" Stretch="Fill" Stroke="#FF5181B9" UseLayoutRounding="False" VerticalAlignment="Bottom" StrokeLineJoin="Bevel" StrokeThickness="3" Grid.ColumnSpan="2"/>
  <TextBlock Margin="8,6,225,8" Grid.Row="1" TextWrapping="Wrap" Text="{Binding BoardListData.MessageData, Mode=OneWay}" VerticalAlignment="Center" FontSize="12" Height="17.4545459747314"/>
  <TextBox x:Name="txtCondition" TextWrapping="Wrap" Foreground="{StaticResource NormalForeColor}" BorderThickness="0,0,0,1" FontSize="12" Style="{StaticResource NormalTextBoxStyle}" HorizontalAlignment="Right" Margin="0,5,82,5" Grid.Row="1" Width="122"/>

  <!--조회 버튼-->
  <Button x:Name="btnSelect" Content="조회" HorizontalAlignment="Right" Margin="0,6,8,7" Width="70" Grid.Column="1" Grid.Row="1" Height="22">
   <i:Interaction.Triggers>
    <i:EventTrigger EventName="Click">
     <i:InvokeCommandAction Command="{Binding SelectConditionCommand, Mode=OneWay}" CommandParameter="{Binding Text, ElementName=txtCondition}"/>
    </i:EventTrigger>
   </i:Interaction.Triggers>
  </Button>
  <!--Line-->
  <Path Data="M0,30 L400,30" Fill="{StaticResource ForeColor_Kakis}" Stretch="Fill" Stroke="{StaticResource ForeColor_Kakis}" UseLayoutRounding="False" StrokeLineJoin="Bevel" StrokeThickness="3" Grid.ColumnSpan="2" Grid.Row="1" Height="3" VerticalAlignment="Bottom" Margin="0,0,0,-1"/>   

 <sdk:DataGrid AutoGenerateColumns="False" Grid.Row="2" IsReadOnly="True"
   x:Name="grdBoardList" RowDetailsVisibilityMode="VisibleWhenSelected"
   ColumnWidth="*" DataContext="{Binding BoardListData.ConditionData}" ItemsSource="{Binding}">
   <sdk:DataGrid.Columns>

                <sdk:DataGridTextColumn x:Name="bOARD_LIST_IDXColumn" Binding="{Binding Path=BOARD_LIST_IDX, Mode=OneWay}" Header="번호" Width="50" />
    <sdk:DataGridTextColumn x:Name="lIST_TITLEColumn" Binding="{Binding LIST_TITLE}" Header="제목" CanUserSort="True" />

    <sdk:DataGridCheckBoxColumn x:Name="lIST_ATTACH_YNColumn" Binding="{Binding LIST_ATTACH_YN}" Header="첨부" Width="50" />

    <sdk:DataGridTextColumn x:Name="rEG_IDXColumn" Binding="{Binding MstMember.MEMBER_NAME}" Header="작성자"  Width="70"/>

    <sdk:DataGridTemplateColumn x:Name="rEG_DTColumn" Header="작성일" Width="70">
     <sdk:DataGridTemplateColumn.CellTemplate>
      <DataTemplate>
       <TextBlock Text="{Binding REG_DT, StringFormat=yyyy.MM.dd}" VerticalAlignment="Center" />
      </DataTemplate>
     </sdk:DataGridTemplateColumn.CellTemplate>
    </sdk:DataGridTemplateColumn>

    <sdk:DataGridTextColumn x:Name="lIST_VIEW_COUNTColumn" Binding="{Binding LIST_VIEW_COUNT, StringFormat=N0}" Header="조회"  Width="50"/>

    </sdk:DataGrid.Columns>
  </sdk:DataGrid>

 </Grid>
</UserControl>

using System.ComponentModel.Composition;
using System.Windows;
using System.Windows.Controls;
using SL5_BOARD.ViewModels;

namespace SL5_BOARD.Views
{
    public partial class BoardListView : UserControl
    {
        [Import(typeof(BoardListViewModel))]
        public BoardListViewModel BoardListVM { get; set; }

        public BoardListView()
        {
            InitializeComponent();

            CompositionInitializer.SatisfyImports(this);

            LayoutRoot.DataContext = BoardListVM;
        }
    }
}

4. 연결된 테이블

BOARD_LIST와 MST_MEMBER 테이블은 서로 연결되어 있다. 이 부분에 대한 Code First 코딩이 앙되어 있으면 작성자명이 출력이 안될 수 있으니 참고 하기 바란다.

5. 언제나 하는 이야기 이지만..
함께 만들어야 의미가 있는 것이다. 일단 목표화면을 보고 자신이 만들어 보고 만들어 보다가 잘 앙되는 부분만 소스를 참고하면 좀더 빠른 실력 향상이 될 수 있으니 참고하도록 한다. 이 화면 이후 부터는 대부분 비슷한 모델 포멧과 뷰모델 포멧을 사용하게 될테니 두 클래스의 형태를 익혀 놓는 것도 좋다. 그리고, 실행하다가 오류가 난다면 꼭 리플로 알려주고, 요청 자료도 리플로 적어주기 바란다.

반응형
댓글