GSI

WPF를 공부 하면서 무언가 만들어 보는 목적이 없다면 공부에 쉽게 지치게 되고 시간을 허비 하게 되는거 같다.
그래서 시작 하였다. "WPF 프로젝!!" 폴더 안의 카테고리는 데모를 제작해 보면서 공부를 하고 데모를 배포 하며, 다른 사람으로 하여금 사용될 수 있는 것을 목표로 한다.

저작권은 본 IamGsi 플로그에 있으며, 배포 또는 사용하는데 있어서 제약이 없습니다.
수정사항이 있거나 아이디어가 있으신 분은 피드백을 해주시면 감사하겠습니다.
단, 상업적인 목적으로 할때는 연락을 주시면 감사하겠습니다.

[프로그램 소개]
본 프로그램은 해당 폴더에 있는 이미지를 화면에 보여 주는 형식입니다.

Posted by gsi
:

일주일 정도 지나고 나니 심사 끝나고 메일이 날라 오네요.

그리고 우선 검색 부분만 제 3단 레이아웃 쪽 오른쪽에 위치 시켜 놨습니다.
다행이 스킨용 플러그인 부분에 추가 하라는 부분이 있어서 그곳에 샥..

다른건 하다 보니 조금 애매해서 조금은 공부 하고 다시 적용해야 할거 같다.
차근 차근.. 공부 한다 생각하고 해봐야 할거 같다.

Posted by gsi
:

PathInfo.cs
----------------------------
using System;
using System.Collections.Generic;
//using System.Linq;
using System.Text;
using System.Collections.ObjectModel;

namespace GsiImageView
{
    public class PathInfo
    {
        private string _path;
        private string _filename;

        public string Path
        {
            get { return _path; }
            set { _path = value; }
        }

        public string FileName
        {
            get { return _filename; }
            set { _filename = value; }
        }

        public PathInfo(string path, string filename)
        {
            this._path = path;
            this._filename = filename;
        }
    }

    public class PathInfoList : ObservableCollection<PathInfo>
    {
        public PathInfoList()
        {
            //최초 입력
            Add(new PathInfo(@"D:\WPF_Project\GsiImageView\Image\1111.jpg", "1111.jpg"));
            Add(new PathInfo(@"D:\WPF_Project\GsiImageView\Image\2222.jpg", "2222.jpg"));
        }
    }
}

Window1.xaml
-------------------------------
<Window
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:c="clr-namespace:GsiImageView"
 xmlns:d="http://schemas.microsoft.com/expression/blend/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:GsiImageView="clr-namespace:GsiImageView"
 x:Class="GsiImageView.Window1"
 x:Name="Window"
 Title="Gsi ImageViewer"
 Width="640" Height="480">

 <Window.Resources>
        <c:PathInfoList x:Key="pathData" />
        <ObjectDataProvider x:Key="PathInfoListDS" d:IsDataSource="True" ObjectType="{x:Type GsiImageView:PathInfoList}"/>
  <DataTemplate x:Key="PathInfoListTemplate">
   <DataTemplate.Resources>
    <Storyboard x:Key="OnLoaded1">
     <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="stackPanel" Storyboard.TargetProperty="(UIElement.Opacity)">
      <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0.1"/>
      <SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="1"/>
     </DoubleAnimationUsingKeyFrames>
    </Storyboard>
   </DataTemplate.Resources>
   <StackPanel HorizontalAlignment="Stretch" Margin="0,2,2,2" x:Name="stackPanel" VerticalAlignment="Stretch" RenderTransformOrigin="0.5,0.5">
    <StackPanel.Background>
     <LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
      <GradientStop Color="#FFA1A1A1" Offset="0"/>
      <GradientStop Color="#FFFFFFFF" Offset="1"/>
     </LinearGradientBrush>
    </StackPanel.Background>
    <StackPanel.RenderTransform>
     <TransformGroup>
      <ScaleTransform ScaleX="1" ScaleY="1"/>
      <SkewTransform AngleX="0" AngleY="0"/>
      <RotateTransform Angle="0"/>
      <TranslateTransform X="0" Y="0"/>
     </TransformGroup>
    </StackPanel.RenderTransform>
    <TextBlock HorizontalAlignment="Stretch" Margin="0,2,0,2" VerticalAlignment="Stretch" Padding="4,0,0,0" Text="{Binding Path=FileName}"/>
    <Border Height="Auto" BorderBrush="#FFCFD6FF" BorderThickness="2,2,2,2" Width="{Binding ElementName=Slider_ImageSize, Path=Value}">
     <Image Width="Auto" Height="Auto" Source="{Binding Path=Path}"/>
    </Border>
   </StackPanel>
   <DataTemplate.Triggers>
    <EventTrigger RoutedEvent="FrameworkElement.Loaded" SourceName="stackPanel">
     <BeginStoryboard Storyboard="{StaticResource OnLoaded1}"/>
    </EventTrigger>
   </DataTemplate.Triggers>
  </DataTemplate>
  <ItemsPanelTemplate x:Key="ItemsPanelTemplate1">
   <WrapPanel/>
  </ItemsPanelTemplate>
 </Window.Resources>

 <Window.Background>
  <LinearGradientBrush EndPoint="0.988,0.988" StartPoint="0.008,0.054">
   <GradientStop Color="#FFB5B5B5" Offset="0"/>
   <GradientStop Color="#FFFFFFFF" Offset="1"/>
  </LinearGradientBrush>
 </Window.Background>

 <Grid x:Name="LayoutRoot">
  <Grid.RowDefinitions>
   <RowDefinition Height="30.192"/>
   <RowDefinition Height="*"/>
  </Grid.RowDefinitions>
  <Label HorizontalContentAlignment="Center" Padding="0,0,0,0" VerticalContentAlignment="Center" HorizontalAlignment="Left" Margin="0,0,0,0" Width="43" Content="경로 :"/>
  <TextBox Background="{x:Null}" BorderBrush="#7F939393" BorderThickness="2,2,2,2" HorizontalContentAlignment="Left" Padding="0,1,0,1" VerticalContentAlignment="Center" Margin="43,0,0,0" x:Name="DirBox" Text="TextBox" TextWrapping="Wrap" HorizontalAlignment="Left" Width="59"/>
  <Button HorizontalAlignment="Right" Margin="0,0,0,0" x:Name="FolderOpen" Width="63" Content="테스트" Click="OnFolderOpenClick"/>
  <ListBox IsSynchronizedWithCurrentItem="True" Background="{x:Null}" Margin="4,4,4,4" x:Name="ImgListBox" Grid.Row="1" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemTemplate="{DynamicResource PathInfoListTemplate}" ItemsPanel="{DynamicResource ItemsPanelTemplate1}" ItemsSource="{Binding Mode=OneWay, Source={StaticResource pathData}}"/>
  <Slider Margin="109,0,70,0" x:Name="Slider_ImageSize" VerticalAlignment="Center" Maximum="1024" Minimum="10" Value="100"/>
 </Grid>
</Window>

Window1.xaml.cs
-----------------------------
using System;
using System.IO;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Threading;

namespace GsiImageView
{
 public partial class Window1
 {
        public delegate void UpdateImage(string _path);

  public Window1()
  {
   this.InitializeComponent();
   
   // Insert code required on object creation below this point.

            //ObjectDataProvider dp = (ObjectDataProvider)this.FindResource("PathInfoListDS");
            //pathInfolist = (PathInfoList)dp.Data;
  }

        private void OnFolderOpenClick(object sender, RoutedEventArgs e)
        {
            //ImgListBox.Items.Add(new PathInfo(@"D:\WPF_Project\GsiImageView\Image\3333.jpg", "3333.jpg"));

            //Window1 w1 = new Window1();
            Thread loadThread = new Thread(new ThreadStart(DataLoad));
            loadThread.Start();
            Thread.Sleep(1);
        }

        private void DataLoad()
        {
            //디렉토리 경로 가져 오기
            DirectoryInfo di = new DirectoryInfo(@"D:\WPF_Project\GsiImageView\Image\MaxImageTest");
            try
            {
                if (di.Exists)
                {
                    //경로가 있음
                    foreach (FileInfo fi in di.GetFiles())
                    {
                        //경로를 타고 세부 이미지 이름을 얻어 온다.
                        string path = di.FullName + "\\" + fi.Name;
                        //il.Add(new PathInfo(path, fi.Name));

                        this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.DataBind, new UpdateImage(UpdateImageList), path);

                        Thread.Sleep(60);
                    }
                }
                else
                {
                    MessageBox.Show("경로가 확실하지 않습니다.");
                    return;
                }
            }
            catch
            {
                MessageBox.Show("경로가 확실하지 않거나, 비정상 오류 입니다.");
                return;
            }
        }

        public void UpdateImageList(string _path)
        {
            PathInfoList pathinfolist = (PathInfoList)this.FindResource("pathData");
            pathinfolist.Add(new PathInfo(_path, "none.jpg"));
//            Thread.Sleep(1);
/*
            //pathInfolist.Add(new PathInfo(_path, "none"));
            ImgListBox.Items.Add(new PathInfo(_path, "none"));
            ImgListBox.UpdateLayout();
            try
            {
                int iii = 0;
            }
            catch(Exception e)
            {
                int iii = 0;
            }
 */
        }
 }
}

Posted by gsi
:

멀티 스레드.. 정리..

C# 2007. 9. 12. 12:59 |

메세지큐에 모든 동작 상태들을 담게 된다.
그리고 그 내용을 메인 스레드에서 실제로 작업 해도 담당하게 된다.

하지만 여기서 다른 스레드와의 동기 여부가 문제가 되며,
다른 스레드에서는 메인스레드에서 생성된 인스턴스된 객체들에 바로 제어를 하지 못한다.

그래서 다른 스레드에서 하는 작업을 메세지 큐에 집어 넣고 메인 스레드가 작업은 해야 한다.
그렇기 때문에 여기서 나오는 내용들이
Invoke, BeginInvoke 가 나오게 된다.

Invoke 해당 내용이 업데이트 될때까지 기다렸다가 다음 행을 시작하게 되며,
BeginInvoke 비동기 적으로 바로 다음 행으로 진행이 되며, 나중에 업데이트가 되게 된다.

...

메인 스레드에게 이러한 작업을 실행해라 하고 다른 스레드에서 위임을 시켜 줘야 한다.

//핸들러 설정
public delegate void UpdateUIHandler(DataSet _dsTmp);

public void GetTable()
{
   Console.Write(...);
   string SQLCommentText = ...
   ....
   Thread.Sleep(1000 * 5);

   //TargetGrid가 태어난 스레드에서 실행을 하게 된다.
   TargetGrid.Invoke(new UpdateUIHandler(UpdateUI), new object[] {_dsTmp});
}

public void UpdateUI(DataSet _dsTmp)
{
   TargetGrid.DataSource = _dsTmp.Tables[0];
}

실행을 하게 되면
내가 다르게 만든 스레드에서 UpdateUI를 하게 되지만 UpdateUI는 메인 스레드에서
작업 하게 된다.

윈도우 어플리케이션에서는 스레드를 사용하지만 다른 스레드에서 사용하지 않고
메인 스레드로 위임 해서 꼭 사용해야 한다.
이럴때 사용하는게 Invoke()가 된다.

BeginInvoke를 Invoke를 사용하게 되면
다음 행은 바로 실행 되고, UpdateUI를 실행하는 스레드는 따로 진행하게 된다.

Posted by gsi
:

공도님이 소개해준 스레드 강좌.. 좋네욤.. 7편까지 있음..
http://vismuri.com/blog_category_12.aspx
Posted by gsi
: