티스토리 뷰

생각보다 시간도 오래걸렸고, 내용도 많아서, 2회에 걸쳐서 진행 하려고 한다. 일단 이번회에는 Model, ViewModel, View 구성에 관한 내용이다. 일단 완성된 화면을 보자..그래야..앞으로 갈길이 멀구나~라는 느낌이 온다.

어떻게 시작을 관리자 페이지에서 사용할 넘을 먼저 만들어서..화면 구성이 머 그냥 그렇다. 역시나 디자이너가 필요해..쿨럭

1. 클라이언트의 전체 적인 레이아웃
1-1. MEF(Manage Extensibility Framework)에 대해 먼저 알아 보고 넘어가야한다. 그동안 다른 강좌에서 MEF 사용에 대해서 이야기를 좀 했었다..음..물론 대충 어떻게 쓰는 거다 정도였지만..그래서 이번에는 좀더 자세하게 한번 다루고 넘어가려고 한다. 왜냐하면 이번 클라이언트는 MEF를 이용한 Export/Import가 다수 존재 하기 때문에 개념이 쉽게 잡히지 않을 수 있기 때문이다.

참고페이지(이 페이지는 꼭 읽어 볼 것을 권한다.)
http://www.c-sharpcorner.com/UploadFile/shivprasadk/3122/

우리가 만든 뷰, 뷰모델, 모델 등은 모두 Export 대상이 될 수 있고 그 Export한 내용들은 Composition Container라는 곳에 모여서 사용되어 지기를 기다라고 있다. 그럼 우린 그 중 필요한 내용들 만 골라서 Import라는 명령을 이용해서 건물을 만들수도, 차를 만들수도 있는 것이다. 그럼 이러한 MEF를 사용 했을때 좋은 점은 무엇인가..

1) 가장 큰 장점은 Decoupled하게 프로그램을 개발 할 수 있다.
Export 대상이 현재 프로젝트 어디 있던지, 아니면 현재 프로젝트가 아니라 웹에 이미 배포가 되어있는 것이라도..Import를 해서 끌어다가 사용 할 수 있으며, Export된 내용이 변경되더라도 Import 한 곳에는 아무런 영향을 미치지 않는다.

2) 하나의 인스턴스를 공유 한다.
하나의 모델이 A라는 aaa뷰에서 Import되고, bbb뷰모델에서 Import되고, ccc모델에서 Import되었을때 3곳에서 사용하는 A라는 Import된 모델은 동일한 내용이다.

3) 실행 중에도 내용이 변경될 수 있다.

등의 여러가지 장점들이 있다...그렇다면 이번에는 프로젝트에서 사용한 내용에 대해서 보도록 하자.


2. SL5_BOARD 프로젝의 전체 구성

2-1. 왜 이런 구성을 가지는가??
우선 BoardContext.cs는 서버와 통신을 통해서 데이터를 조회하고, 저장하는 SL5_BOARDDomainContext가 존재하며, 이 것을 통해서 가지고 온 데이터를 컨텍스트로서 로컬에서 관리를 할 수 있도록 하기위해서이다. 

모델 클래스는 BoardContext를 모두 Import를 받아서 하나의 로컬 저장소의 데이터를 모델 별로 관리를 할 수 있도록 만들어 놓은 것이고, 뷰모델은 뷰에서 사용할 ICommand와 비지니스 로직을 관리하며, 뷰는 사용자와의 인터렉션을 할 수 있도록 나누어 놓은 것이다..

최종적으로 모든 뷰는 ImportMany라는 명령을 통해서 MainPage.xaml에 Import되어 사용 되어 질 것이다.

이런 구성을 만들기 위해 나름 고민을 만이 했기 때문에..음음..아주 최고의 모델은 아니라도 마구 만들어진 모델은 아니니 나중에라도 이런 구성은 가지고 가서 사용해도 괜찮을 것이다. 참고로 이렇게 만들어 놓아야 진정한 Model-View-ViewModel이 되는 것이다..(처음부터 이렇게 만들면 개발 시간이 막코딩하는 것보다 시간이 2배 정도는 더 든다;;;..그러나 나중에 유지 보수하는 시간 까지 놓고 전체 적으로 본다면 이런 개발 패턴이 훨씬 유지보수하는데 효율적이다.)

2-2. SL5_BOARD 프로젝트에 리퍼런스 추가

Add Reference

Microsoft.Expression.Interactions 5.0.5.0
System.ComponentModel.Composition 5.0.5.0
System.ComponentModel.Composition.Initialization 5.0.5.0
System.Windows.Interactivity 5.0.5.0

3. Models

BoardContext.cs

//이 모델은 아~무것도 없다..그냥 통신하기 위한 컨텍스트만 하나 달랑있다~

using System.ComponentModel;
using System.ComponentModel.Composition;
using SL5_BOARD.Web.DomainService;

namespace SL5_BOARD.Models
{
    //Export한다~
    [Export(typeof(BoardContext))]
    public class BoardContext : INotifyPropertyChanged
    {
        SL5_BOARDDomainContext context;
        public SL5_BOARDDomainContext Context
        {
            get
            {
                return context;
            }

            private set
            {
                if (context != null)
                {
                    context = value;
                    OnPropertyChanged("Context");
                }
            }
        }

        #region PropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

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

        public BoardContext()
        {
            context = new SL5_BOARDDomainContext();
        }
    }
}

BoardMain.cs

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


namespace SL5_BOARD.Models
{
    //BoardMain 모델을 익스포트 시킨다.
    [Export(typeof(BoardMain))]
    public class BoardMain : INotifyPropertyChanged
    {
        //컨텍스트를 임포트 시킨다
        [Import(typeof(BoardContext))]
        public BoardContext BoardDomainService { get; set; }

        //너무 길어서 짧게 쓸려고 만들어 놓은것 - 뷰단에서 이걸 바인딩 한다.
        public EntitySet<BOARD_MAIN> CollectionData
        {
            get
            {
                return BoardDomainService.Context.BOARD_MAINs;
            }
        }

        //게시판 종류 목록 바인딩 하기 위해
        public ObservableCollection<CBoardType> BoardTypeCol { get; set; }

        //게시판 상태 바인딩용 - 이게 잘 앙대는 것 중에 하나인데;; 라디오버튼 앞으로 사용하지 말아야할듯 ㅋ
        //별것두 아닌데..바인딩으로 처리할려니 할일이 대폭 늘어난다;;
        string boardStateText;
        public string BoardStateText
        {
            get
            {
                return boardStateText;
            }
            set
            {
                if (boardStateText != value)
                {
                    boardStateText = value;

                    switch (boardStateText)
                    {
                        case "준비중":      //준비중
                            CurrentData.BOARD_STATE = "01";
                            break;
                        case "사용중":      //사용중
                            CurrentData.BOARD_STATE = "02";
                            break;
                        case "일시중지":    //일시중지
                            CurrentData.BOARD_STATE = "03";
                            break;
                        case "삭제":        //삭제
                            CurrentData.BOARD_STATE = "04";
                            break;
                    }
                    OnPropertyChanged("BoardStateText");
                }
            }
        }

        //현재 선택되어있는 보드메인
        BOARD_MAIN currentData;
        public BOARD_MAIN CurrentData
        {
            get
            {
                return currentData;
            }
            set
            {
                if (currentData != value)
                {
                    currentData = value;
                    OnPropertyChanged("CurrentData");
                }
            }
        }

        //각종 메시지 출력용
        string messageData;
        public string MessageData
        {
            get
            {
                return messageData;
            }
            private set
            {
                if (messageData != value)
                {
                    messageData = "[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "] " + value;
                    OnPropertyChanged("MessageData");
                }
            }
        }

        //만들어 놓기는 했는데..아직 사용은 앙대고 있다. 불러온 카운트를 넣어서 사용할 예정
        int maxCount;
        public int MaxCount
        {
            get
            {
                return maxCount;
            }
            private set
            {
                if (maxCount != value)
                {
                    maxCount = value;
                    OnPropertyChanged("MaxCount");
                }
            }
        }

        #region PropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

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

        //생성자
        public BoardMain()
        {
            //게시판 종류 설정
            BoardTypeCol = new ObservableCollection<CBoardType>
            {
                new CBoardType{BoardType = "NOR", BoardTypeComboText="일반게시판"},
                new CBoardType{BoardType = "PIC", BoardTypeComboText="사진게시판"},
                new CBoardType{BoardType = "ETC", BoardTypeComboText="기타게시판"}
            };
            this.PropertyChanged += new PropertyChangedEventHandler(BoardMain_PropertyChanged);
        }

        //자기 자신이 프로퍼티 체인지 이벤트 발생시 연속적인 다른 프로퍼티를 고치는 용도
       void BoardMain_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "CurrentData":
                    if (CurrentData != null)
                    {

                        //음..라디오 박스 때문에 신경썼는데..처음에만 대구 나중에는 잘 앙된다..원인은 불명
                        switch (CurrentData.BOARD_STATE)
                        {
                            case "01":      //준비중
                                BoardStateText = "준비중";
                                break;
                            case "02":      //사용중
                                BoardStateText = "사용중";
                                break;
                            case "03":      //일시중지
                                BoardStateText = "일시중지";
                                break;
                            case "04":      //삭제
                                BoardStateText = "삭제";
                                break;
                        }
                    }
                    else
                    {
                        BoardStateText = "";
                    }
                    break;
            }
        }

        //데이터 조회
        public void Getting()
        {
            if (BoardDomainService.Context.IsLoading == false)
            {
                BoardDomainService.Context.GetBoardMainQuery().IncludeTotalCount = true;
                BoardDomainService.Context.Load(BoardDomainService.Context.GetBoardMainQuery(), LoadBehavior.RefreshCurrent, true);
            }
            else
            {
                MessageData = "조회 중이니 잠시 후 다시 시도해 주시기 바랍니다.";
            }
        }

        //데이터 추가 - SubmitChange()전 까지는 로컬에만 존재한다.
        public void Adding(BOARD_MAIN bm)
        {
            if (bm != null && bm is BOARD_MAIN)
            {
                bm.REG_DT = DateTime.Now;
                bm.REG_IDX = 1;
                BoardDomainService.Context.BOARD_MAINs.Add(bm);
                CurrentData = bm;
            }
            else
            {
                MessageData = "데이터가 없거나 형식이 다릅니다.";
            }
        }

        //데이터 삭제 
        public void Removing(BOARD_MAIN bm)
        {
            if (bm != null && bm is BOARD_MAIN)
            {
                BoardDomainService.Context.BOARD_MAINs.Remove(bm);
            }
            else
            {
                MessageData = "데이터가 없거나 형식이 다릅니다.";
            }
        }

        //저장
        public void Saving()
        {

            //저장된 결과를 알기 위해 콜백 함수를 지정
            BoardDomainService.Context.SubmitChanges(submitCallBack, null);
        }


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

        //작업 취소
        public void Canceling()
        {
            BoardDomainService.Context.RejectChanges();
        }

    }
}


4. ViewModel

BoardMainViewModel.cs

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;

namespace SL5_BOARD.ViewModels
{
    //뷰모델 익스포트
    [Export(typeof(BoardMainViewModel))]
    public class BoardMainViewModel : INotifyPropertyChanged
    {
        #region PropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

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

         //모델 인포트
        [Import(typeof(BoardMain))]
        public BoardMain BoardMainData { get; set; }

        public BoardMainViewModel()
        {
            //BoardMainData.BoardTypeCol
        }

        //조회커맨드
        ICommand selectCommand;
        public ICommand SelectCommand
        {
            get
            {
                if (selectCommand == null)
                {
                    selectCommand = new ActionCommand(() =>
                    {
                        BoardMainData.Getting();
                    });
                }
                return selectCommand;
            }
        }

        //조회 함수 - 맨처음에 조회를 하기 위해서..
        public void Select()
        {
            BoardMainData.Getting();
        }

        //추가 커맨드
        ICommand addCommand;
        public ICommand AddCommand
        {
            get
            {
                if (addCommand == null)
                {
                    addCommand = new ActionCommand(() =>
                    {
                        BOARD_MAIN bm = new BOARD_MAIN();
                        bm.BOARD_NAME = "신규 게시판의 명칭을 입력하세요";
                        bm.BOARD_DESC = "신규 게시판의 설명을 입력하세요";
                        BoardMainData.Adding(bm);
                    });
                }
                return addCommand;
            }
        }

        //삭제 커맨드
        ICommand removeCommand;
        public ICommand RemoveCommand
        {
            get
            {
                if (removeCommand == null)
                {
                    removeCommand = new ActionCommand(p =>
                    {
                        if (p != null)
                        {
                            BOARD_MAIN bm = p as BOARD_MAIN;
                            BoardMainData.Removing(bm);
                        }
                    });
                }
                return removeCommand;
            }
        }

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

        //취소 커맨드
        ICommand cancelCommand;
        public ICommand CancelCommand
        {
            get
            {
                if (cancelCommand == null)
                {
                    cancelCommand = new ActionCommand(() =>
                    {
                        BoardMainData.Canceling();
                    });
                }
                return cancelCommand;
            }
        }
        
        //리스트 박스에서 선택항목 변경시
        ICommand selectChanged;
        public ICommand SelectChangedCommand
        {
            get
            {
                if (selectChanged == null)
                {
                    selectChanged = new ActionCommand(para => SelectChangedOperation(para));
                }
                return selectChanged;
            }
        }
        private void SelectChangedOperation(object para)
        {
            BoardMainData.CurrentData = para as BOARD_MAIN;
        }

        //라디오 버튼에서 클릭시 - 라디오 버튼;;;이렇게까지 했는대두 결국 잘 앙대구..짬뽕남;;
        ICommand changeStateCommand;
        public ICommand ChangeStateCommand
        {
            get
            {
                if (changeStateCommand == null)
                {
                    changeStateCommand = new ActionCommand(para => ChangeStateOperation(para));
                }
                return changeStateCommand;
            }
        }
        private void ChangeStateOperation(object para)
        {
            BoardMainData.BoardStateText = para as string;
        }
    }
}

5. View

BoardMainView.xaml

<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:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:SL5_BOARD_Converter="clr-namespace:SL5_BOARD.Converter"
    x:Name="userControl"
    x:Class="SL5_BOARD.Views.BoardMainView"
    mc:Ignorable="d"
    d:DesignHeight="500" d:DesignWidth="600">
   
 <UserControl.Resources>

   <!--바인딩 컨버터 사용 할 수 있도록... -->
  <SL5_BOARD_Converter:ValueToBoolConverter x:Key="ValueToBoolConverter"/>
  <SL5_BOARD_Converter:BoardTypeConverter x:Key="BoardTypeConverter"/>
 </UserControl.Resources>
   
    <Grid x:Name="LayoutRoot" Background="White">

     <!--조회 커맨드 실행-->
     <i:Interaction.Triggers>
      <i:EventTrigger>
       <i:InvokeCommandAction Command="{Binding SelectCommand, Mode=OneWay}"/>
      </i:EventTrigger>
     </i:Interaction.Triggers>
     <Grid.ColumnDefinitions>
      <ColumnDefinition Width="192"/>
      <ColumnDefinition/>
     </Grid.ColumnDefinitions>
     <Grid.RowDefinitions>
      <RowDefinition Height="38"/>
      <RowDefinition Height="35"/>
      <RowDefinition/>
      <RowDefinition Height="35"/>
     </Grid.RowDefinitions>
     <Grid.DataContext>

      <!--디자인 타임에서 사용하기 위해 넣어 놓은 부분-->
      <SL5_BOARD_ViewModels:BoardMainViewModel/>
     </Grid.DataContext>

      <!--사실 이걸 다 읽는다고 이쁜 디자인이 되는 것도 아니니..디자인 부분은 넘어가겠다..-->
     <TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="게시판 관리" FontSize="14.667" FontWeight="Bold" Foreground="{StaticResource ForeColor_Blues}" Margin="10,6,0,10" d:LayoutOverrides="Height"/>
     <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"/>
     <Button x:Name="btnSelect" Content="조회" HorizontalAlignment="Right" Margin="0,6,8,7" Width="70" Grid.Column="1" Grid.Row="1" Height="22"/>
     <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"/>
     <TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="게시판 목록" FontSize="12" FontWeight="Bold" Foreground="{StaticResource ForeColor_Kakis}" Margin="10,0,0,368" Grid.Row="2" VerticalAlignment="Bottom"/>

 

     <!--아까 모델에서 만들었던 CollectionData를 여기 ItemsSource에 바인딩 한다. 그리고, 아이템 템플릿을 이용해서 데이터를 뿌려준다.-->
     <ListBox x:Name="lbBoardMain" Margin="8,27,8,8" Grid.Row="2" BorderBrush="{x:Null}" ItemsSource="{Binding BoardMainData.CollectionData}" ItemTemplate="{StaticResource BoardMainDataTemplate}">
      <i:Interaction.Triggers>

       <!--아까 뷰모델에서 만들어 놓았던 SelectChangedCommand를 여기서 사용한다-->
       <i:EventTrigger EventName="SelectionChanged">
        <i:InvokeCommandAction Command="{Binding SelectChangedCommand, Mode=OneWay}" CommandParameter="{Binding SelectedItem, ElementName=lbBoardMain}"/>
       </i:EventTrigger>
      </i:Interaction.Triggers>
     </ListBox>

     <TextBlock TextWrapping="Wrap" Text="게시판 상세 정보" FontSize="12" FontWeight="Bold" Foreground="{StaticResource ForeColor_Kakis}" Margin="8,0,0,367" Grid.Row="2" VerticalAlignment="Bottom" HorizontalAlignment="Left" Grid.Column="1"/>

     <!--게시판 상세 정보가 들어가는 스택패널 여기서 CurrentData를 바인딩 한다.-->
     <StackPanel x:Name="spBoardMainInfo" Margin="8,27,8,8" Grid.Column="1" Grid.Row="2" DataContext="{Binding BoardMainData.CurrentData}">
      <StackPanel Orientation="Horizontal" Height="28">
       <Ellipse Fill="#FF666666" Stroke="Black" Width="5" Height="5" VerticalAlignment="Center" Margin="10,0,0,0"/>
       <TextBlock TextWrapping="Wrap" Text="명칭" FontSize="12" VerticalAlignment="Center" Width="70" Padding="5,0,0,0"/>
       <TextBox TextWrapping="Wrap" Text="{Binding BOARD_NAME, Mode=TwoWay}" Foreground="{StaticResource NormalForeColor}" BorderThickness="0,0,0,1" FontSize="12" VerticalAlignment="Center" Style="{StaticResource NormalTextBoxStyle}"/>
      </StackPanel>

      <StackPanel Orientation="Horizontal" Height="28">
       <Ellipse Fill="#FF666666" Stroke="Black" Width="5" Height="5" VerticalAlignment="Center" Margin="10,0,0,0"/>
       <TextBlock TextWrapping="Wrap" Text="종류" FontSize="12" VerticalAlignment="Center" Width="70" Padding="5,0,0,0"/>
       <ComboBox Width="120" VerticalAlignment="Center" Foreground="{StaticResource NormalForeColor}" ItemsSource="{Binding Path=DataContext.BoardMainData.BoardTypeCol, ElementName=LayoutRoot}" DisplayMemberPath="BoardTypeComboText" SelectedValuePath="BoardType" SelectedValue="{Binding BOARD_TYPE, Mode=TwoWay}"/>
      </StackPanel>

      <StackPanel Orientation="Horizontal" Height="28">
       <Ellipse Fill="#FF666666" Stroke="Black" Width="5" Height="5" VerticalAlignment="Center" Margin="10,0,0,0"/>
       <TextBlock TextWrapping="Wrap" Text="로그인확인" FontSize="12" VerticalAlignment="Center" Width="70" Padding="5,0,0,0"/>
       <CheckBox Content="{Binding MEMBER_CHECK}" VerticalAlignment="Center" Foreground="{StaticResource NormalForeColor}" IsChecked="{Binding MEMBER_CHECK, Mode=TwoWay}"/>
      </StackPanel>

      <StackPanel Orientation="Horizontal" Height="28">
       <Ellipse Fill="#FF666666" Stroke="Black" Width="5" Height="5" VerticalAlignment="Center" Margin="10,0,0,0"/>
       <TextBlock TextWrapping="Wrap" Text="설명" FontSize="12" VerticalAlignment="Center" Width="70" Padding="5,0,0,0"/>
       <TextBox TextWrapping="Wrap" Text="{Binding BOARD_DESC, Mode=TwoWay}" Foreground="{StaticResource NormalForeColor}" BorderThickness="0,0,0,1" FontSize="12" VerticalAlignment="Center" Style="{StaticResource NormalTextBoxStyle}"/>
      </StackPanel>

      <StackPanel Orientation="Horizontal" Height="28" >
       <Ellipse Fill="#FF666666" Stroke="Black" Width="5" Height="5" VerticalAlignment="Center" Margin="10,0,0,0"/>
       <TextBlock TextWrapping="Wrap" Text="상태" FontSize="12" VerticalAlignment="Center" Width="70" Padding="5,0,0,0"/>
       <RadioButton x:Name="radioButton" Content="준비중" VerticalAlignment="Bottom" Foreground="{StaticResource NormalForeColor}" Margin="0,0,0,5" GroupName="BoardState"
     IsChecked="{Binding ElementName=LayoutRoot, Path=DataContext.BoardMainData.BoardStateText, ConverterParameter=준비중, Converter={StaticResource ValueToBoolConverter}, Mode=OneWay}" Command="{Binding DataContext.ChangeStateCommand, ElementName=LayoutRoot}" CommandParameter="{Binding Content, ElementName=radioButton}"/>
       <RadioButton x:Name="radioButton1" Content="사용중" VerticalAlignment="Bottom" Foreground="{StaticResource NormalForeColor}" Margin="8,0,0,5" GroupName="BoardState"
     IsChecked="{Binding ElementName=LayoutRoot, Path=DataContext.BoardMainData.BoardStateText, ConverterParameter=사용중, Converter={StaticResource ValueToBoolConverter}, Mode=OneWay}" Command="{Binding DataContext.ChangeStateCommand, ElementName=LayoutRoot}" CommandParameter="{Binding Content, ElementName=radioButton1}"/>
       <RadioButton x:Name="radioButton2" Content="일시중지" VerticalAlignment="Bottom" Foreground="{StaticResource NormalForeColor}" Margin="8,0,0,5" GroupName="BoardState"
     IsChecked="{Binding ElementName=LayoutRoot, Path=DataContext.BoardMainData.BoardStateText, ConverterParameter=일시중지, Converter={StaticResource ValueToBoolConverter}, Mode=OneWay}" Command="{Binding DataContext.ChangeStateCommand, ElementName=LayoutRoot}" CommandParameter="{Binding Content, ElementName=radioButton2}"/>
       <RadioButton x:Name="radioButton3" Content="삭제" VerticalAlignment="Bottom" Foreground="{StaticResource NormalForeColor}" Margin="8,0,0,5" GroupName="BoardState"
     IsChecked="{Binding ElementName=LayoutRoot, Path=DataContext.BoardMainData.BoardStateText, ConverterParameter=삭제, Converter={StaticResource ValueToBoolConverter}, Mode=OneWay}" Command="{Binding DataContext.ChangeStateCommand, ElementName=LayoutRoot}" CommandParameter="{Binding Content, ElementName=radioButton3}"/>
      </StackPanel>

            <StackPanel Orientation="Horizontal" Height="28">
             <Ellipse Fill="#FF666666" Stroke="Black" Width="5" Height="5" VerticalAlignment="Center" Margin="10,0,0,0"/>
             <TextBlock TextWrapping="Wrap" Text="순서" FontSize="12" VerticalAlignment="Center" Width="70" Padding="5,0,0,0"/>
             <TextBox TextWrapping="Wrap" Text="{Binding BOARD_ORDER, Mode=TwoWay}" Foreground="{StaticResource NormalForeColor}" BorderThickness="0,0,0,1" FontSize="12" VerticalAlignment="Center" Style="{StaticResource NormalTextBoxStyle}"/>
            </StackPanel>

     </StackPanel>
     <!--게시판 상세 정보 패널 끝-->

      <!--각종 버튼들-->
    <Button x:Name="btnAdd" Content="추가" Margin="0,3,8,0" Grid.Row="2" VerticalAlignment="Top" HorizontalAlignment="Right" Width="70" Height="22">
      <i:Interaction.Triggers>
       <i:EventTrigger EventName="Click">
        <i:InvokeCommandAction Command="{Binding AddCommand, Mode=OneWay}"/>
       </i:EventTrigger>
      </i:Interaction.Triggers>
     </Button>

     <Button x:Name="btnSave" Content="저장" Margin="0,3,82,0" Grid.Row="2" VerticalAlignment="Top" Height="22" Grid.Column="1" HorizontalAlignment="Right" Width="70">
      <i:Interaction.Triggers>
       <i:EventTrigger EventName="Click">
        <i:InvokeCommandAction Command="{Binding SaveCommand, Mode=OneWay}"/>
       </i:EventTrigger>
      </i:Interaction.Triggers>
     </Button>

     <Button x:Name="btnCancel" Content="취소" Margin="0,3,8,0" Grid.Row="2" VerticalAlignment="Top" Height="22" Grid.Column="1" HorizontalAlignment="Right" Width="70">
      <i:Interaction.Triggers>
       <i:EventTrigger EventName="Click">
        <i:InvokeCommandAction Command="{Binding CancelCommand, Mode=OneWay}"/>
       </i:EventTrigger>
      </i:Interaction.Triggers>
     </Button>
     <TextBlock Margin="8,6,82,8" Grid.Row="1" TextWrapping="Wrap" Text="{Binding BoardMainData.MessageData, Mode=OneWay}" Grid.ColumnSpan="2" VerticalAlignment="Center" FontSize="12"/>

    </Grid>
</UserControl>

BoardMainView.xaml.cs

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

namespace SL5_BOARD.Views
{
    //아직 이넘은 익스포트 앙시켰음
    public partial class BoardMainView : UserControl
    {
        //뷰모델 임포트
        [Import(typeof(BoardMainViewModel))]
        public BoardMainViewModel BoardMainVM { get; set; }

        public BoardMainView()
        {
            InitializeComponent();

            //MEF 초기화
            CompositionInitializer.SatisfyImports(this);

            //ViewModel을 최상위 DataContext에 쑤셔넣구
            LayoutRoot.DataContext = BoardMainVM;
        }

    }
}


6. 너무 길다..작업 시간이 어제 저녁 부터 시작해서 오늘 오후에 끝났으니..음..한 7-8 시간은 작업을 한듯하니..양도 많아서..한번에 올리기가 부담스러운.. 작업을 하면서도 이거 게시판에 어떻게 올리나 한참 궁시렁 거리면서 작업을 했었는데..흐흐흐..원래는 개발하면서 주석을 잘 다는 편인데..이상하게 실버라이트 만들때는 주석 달기가 싫타;; 그래서 소스에 주석이 없어서 소스를 올려도 보기가 쉽지는 않치만..음음.. 일단 뭔가 제대로 돌아가는 듯한 모양을 갖추었으니.. 전체 소스를 한번 올리도록 하겠다.

 여기서 다루지 않았던 컨버터 부분과 게시판 종류를 콤보박스에 표시하기 위해서 약간 먼가 처리한 부분들을 추가로 보면 되고.. 만은 도움이 되었으면 한다. 그리고 디자인 해주실분~ 다시 구해본다..(구해질때까징..ㅜㅜ) 이제 좀있음 여러 화면 떠서 아이폰에서 클릭하면 옆으로 휙하고 지나가고 다시 돌아오는 애니메이션 기능 넣구 싶은뎅..이힝..알려주실분도 좋구..도와주실분도..좋쿠..좀..

댓글
댓글쓰기 폼
Total
641,239
Today
153
Yesterday
311
«   2021/10   »
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31            
10-22 12:49
글 보관함