노무현 전 대통령 서거 - 삼가 고인의 명복을 빕니다

2010년의 새해가 밝았습니다. 연말연시가 되면 지난 해를 뒤돌아보고 다가오는 새로운 해를 조망하는 다양한 예측이 쏟아지는데, 오늘 소개할 내용은 ‘2010년을 뒤흔들 10가지 기술’에 대한 것입니다. 유명한 IT 팀블로그인 테크크런치에서 발표한 내용(원문은 Ten Technologies that will rock 2010)인데 IT쪽에 종사하시는 분들에게 유용한 내용인 것 같아 소개하고자 합니다.

The Tablet

아무래도 애플에서 1월26일에 발표한다는 태블릿(제품명이 iSlate가 유력하다고 하죠)이 아이폰만큼의 폭발적인 반응을 이끌어낼 수 있을지 기대되는 부분입니다. 애플 태블릿 소문에 대해 정리가 잘 된 곳이 있으니 참고하시기 바랍니다. 아이폰, 안드로이드폰 등 휴대폰도 있고 10인치 크기의 넷북도 있는데 과연 태블릿은 어떤 용도로 이용될까요? 최근 ‘킨들’이 일으킨 이북리더 기능과 더불어 웹TV 서비스가 들어갈거라는 예측도 있는데 점점 궁금해집니다.

위치기반서비스(Geo)

GPS가 탑재된 모바일 기기가 늘어나면서 2010년에는 위치기반 서비스도 폭발적으로 늘어날 것으로 예상됩니다. 트위터는 이미 API를 공개한 바 있고 최근에는 위치기반 서비스를 강화하기 위해 GeoAPI를 인수했습니다. 트위터의 경우 모바일에서 이용하는 경우가 점점 많아지고 있는데, 올해에는 위치기반 서비스를 트위터가 자체적으로 제공할 것이라는 예상까지 나오고 있네요. 해외는 물론 국내에서도 점점 인기를 얻고 있는 포스퀘어(Foursquare)도 있구요. 페이스북도 이용자의 상태 업데이트에 위치기반 서비스를 접목할 것이라고 하는군요. 아이폰에서 구글 검색을 해보면 자신의 현재 위치에서 가장 가까운 곳의 정보를 보여주는 주변 검색이 가능합니다. 국내에서는 어떤 서비스가 나올지 궁금해집니다.

실시간검색(Realtime Search)

작년에 트위터가 폭발적인 인기를 끌면서 ‘현재 일어나고 있는 일(Waht’s happening)’에 대한 관심이 높아지고 검색에도 실시간 검색이 점점 더 중요해지고 있습니다. 이미 구글과 마이크로소프트의 빙(Bing)은 트위터와의 제휴를 통해 실시간 트윗을 검색 결과에 반영하고 있으며, 야후도 그 대열에 합류했습니다.

검색어에 가장 적합한 결과뿐 아니라 해당 검색어에 대한 현재의 반응을 살펴보는 것이 기업의 마케팅 활동에도 점점 더 중요해지고 있습니다.

크롬OS

요즘 구글이 밀고 있는 운영체제입니다. 구글은 크롬이라는 웹브라우저를 제공하고 있는데, 향후 웹브라우저 중심의 운영체제를 만드려는 야심을 드러내고 있고 그 중심에 크롬OS가 있습니다. 올해 안에는 크롬OS를 탑재한 넷북이 출시될 것이라는 소문도 돌고 있죠. 위에서 살펴봤던 태블릿도 크롬OS를 채택한 것이 곧 출시될거라는 소문도 있구요.

이 글을 쓰고 있는 동안에 구글폰인 넥서스원처럼 구글과 HTC가 크롬OS를 탑재한 태블릿을 만들기 위해 1년6개월 동안 일해왔다는 소문도 들리네요. 올해에는 크롬OS를 채택한 다양한 단말이 출현할 것 같은 예감이 팍팍 듭니다. 마이크로소프트뿐만 아니라 애플도 바짝 긴장해야 할 듯 하군요.

HTML5

올해에는 HTML5도 눈여겨 봐야 합니다. 구글은 최근 ‘기어스(Gears)’ 개발을 중단하고 HTML5를 밀기로 했다고 하는데요. HTML5가 되면 동영상을 보기 위해 어도비 플래시나 마이크로소프트의 실버라이트 등의 플러그인을 설치할 필요가 없어집니다. 또한 웹브라우저에서 오프라인 상태에서도 데이터를 저장하는 것도 가능해지고 드래그앤드롭(Drag&Drop)이 가능해지는 등 웹 자체가 데스크톱 애플리케이션처럼 동작할 수 있게 됩니다.

작년부터 클라우드 서비스가 각광을 받고 있는데 웹에 HTML5가 보급될수록 클라우드 서비스의 발전 속도는 더 빨라질 것 같습니다. 클라우드 서비스와 이를 위한 운영체제인 크롬OS를 밀고 있는 구글에서 HTML5를 대대적으로 밀겠죠.

Mobile Video

모바일 기기에 카메라 기능이 추가된 것은 최근 일도 아니지만 모바일폰에서 동영상을 찍어 실시간으로 스트리밍하는 서비스가 점점 더 늘어가고 있습니다. 물론 실시간 스트리밍 영상을 모바일폰에서 시청하는 것도 늘어나고 있구요.

증강현실(Augmented Reality)

작년부터 증강현실이라는 용어도 많이 들어보셨나요? 모바일폰의 카메라로 보이는 실시간 이미지 위에 사진이나 트위터의 글(tweet), 또는 기타 유용한 정보를 추가할 수 있다는 개념인데, 올해에는 더욱 큰 사랑을 받을 것으로 예상됩니다. 자세한 내용은 증강현실에 대해 소개를 많이 해 주신 하이컨셉님의 글을 참고하시기 바랍니다.

Mobile Transactions

모바일폰이 점점 더 발전하면서 이제 모바일폰으로 신용카드 결재를 할 수 있는 시대가 도래하고 있습니다. 트위터의 공동창업자 중의 한 명이 아이폰을 신용카드 리더기로 만들 수 있는 Square라는 서비스를 제공하고 있으며, Mophie에서도 비슷한 컨셉의 서비스를 내놓았다고 하는군요.

기본 개념을 살펴보면, 모든 모바일 단말이 POS 단말이 될 수 있고 거래 정보는 기업의 회계, CRM 등과 연동될 수 있다는 것인데, 좀 무섭네요.

안드로이드(Android)

내년 1월6일에 일반에 공개될 예정인 구글폰 넥서스원으로 인해 구글의 개방형 모바일 플랫폼인 ‘안드로이드’가 더욱 더 주목받을 것 같습니다. 작년에도 안드로이드를 채택한 모바일 단말기가 출시되었는데, 올해부터는 애플의 아이폰 대항마로 확고한 자리를 잡을 것으로 예상되는군요. 국내에서도 KT의 아이폰에 대항하기 위해 SKT와 LGT에서 안드로이드폰을 많이 출시한다고 하니 국내 이용자들도 곧 확인할 수 있을 것 같습니다.

Social CRM

트위터와 페이스북이 불러일으킨 실시간 소셜 미디어(커뮤니케이션)의 흐름이 기업으로도 확산되고 있으며, 기업내에서도 이를 잘 활용하기 위한 다양한 서비스가 등장하고 있습니다. 트위터의 기업용 버전으로 확고하게 자리를 잡아가는 Yammer가 있고 제 블로그를 통해 소개해 드렸던 소셜캐스트(Socialcast), 기업용 CRM 시장의 강자인 세일즈포스닷컴이 제공하는 Chatter 등의 서비스가 있습니다. 국내 업체에서 이런 서비스를 제공하는 곳은 아직 한 곳도 없는데 올해 관심을 가져야 하는 분야입니다.

Trackback 0 | Comment 0
 
(Visual Studio 2008) 에서 Command Argument 설정하는 방법
 
# Project -> <YourProjectName> Properties ->
                                                     Configuration Properties -> Debugging -> Command Arguments



1.  App.xaml.cs에 onStartup메소드를 재정의 한다.  

  • ArbitraryArgname 부분에 Argument명을 설정할수 있다.
  • Args 의 배열을 늘려서 더 많은 Argumnet인자를 메인으로 보낼수 있다.
   1: protected override void OnStartup(StartupEventArgs e)
   2: {
   3:     if (e.Args != null && e.Args.Count() > 0)
   4:     {
   5:         this.Properties["ArbitraryArgName"] = e.Args[0];
   6:     }
   7:  
   8:     base.OnStartup(e);
   9: }



 2.  생성자에서 Loaded 이벤트를 생성한다.
  • 설정했던 Argument명으로 넘어온 인자를 받아낸다. 
   1: public MainContainer()
   2: {
   3:     InitializeComponent();
   4:  
   5:     // Make sure we handle command line args:
   6:     this.Loaded += new RoutedEventHandler(MainContainer_Loaded);
   7: }
   8:  
   9: void MainContainer_Loaded(object sender, RoutedEventArgs e)
  10: {
  11:     if (Application.Current.Properties["ArbitraryArgName"] != null)
  12:     {
  13:         string fname = Application.Current.Properties["ArbitraryArgName"].ToString();
  14:         // Act on the file...
  15:     }
  16: }
Trackback 0 | Comment 0

출처 : http://blogs.msdn.com/marcelolr/archive/2007/06/09/basics-of-data-bound-drag-drop-in-wpf.aspx

Also known as "how do I perform drag-drop between two data-bound list boxes"? Well, excellent question - here's a first shot at the answer, although there is much polish that could be added.

This really isn't all that different from the series that was started a long time ago. Let's start with a simple WPF project and add this to the main window.

<Window x:Class="BoundListBoxDragDrop.Window1"
    xmlns="
http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="
http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300" Loaded="Window_Loaded">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <TextBlock Grid.ColumnSpan="2" TextWrapping="WrapWithOverflow">
            The ListBox controls are bound to ObservableCollection&lt;string&gt; collections.
            <LineBreak />
            Drag and drop works great!
        </TextBlock>
        <ListBox Grid.Row="1" Name="ListBox1" />
        <ListBox Grid.Row="1" Grid.Column="1" Name="ListBox2" />
    </Grid>
</Window>

Now, we'll add some fake data in the loaded method, and prepare the ListBox instances to deal be drag sources and targets.

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    ListBox1.ItemsSource = new ObservableCollection<string>(new List<string>(new string[] { "Red", "Green", "Blue" }));
    ListBox2.ItemsSource = new ObservableCollection<string>(new List<string>(new string[] { "North", "South", "East", "West" }));

    PrepareListBoxForDragDrop(ListBox1);
    PrepareListBoxForDragDrop(ListBox2);
}

The PrepareListBoxForDragDrop will mostly wire up events we're interested in to handle the flow of things.

private void PrepareListBoxForDragDrop(ListBox listbox)
{
    listbox.AllowDrop = true;
    listbox.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(ListboxPreviewMouseLeftButtonDown);
    listbox.PreviewMouseMove += new MouseEventHandler(ListboxPreviewMouseMove);
    listbox.PreviewMouseLeftButtonUp += new MouseButtonEventHandler(ListboxPreviewMouseLeftButtonUp);
    listbox.Drop += new DragEventHandler(ListboxDrop);
}

Now, we'll take this bit by bit, but because I'm feeling extra-lazy today, I decided to make sure that every ListBox had its own set of variables and not scope everything to the window like I did before, so here are a few DependencyProperty declarations to the rescue.

private static DependencyProperty DraggingElementProperty = DependencyProperty.RegisterAttached(
    "DraggingElement", typeof(string), typeof(Window1), new FrameworkPropertyMetadata(null));
private static DependencyProperty IsDownProperty = DependencyProperty.RegisterAttached(
    "IsDown", typeof(bool), typeof(Window1), new FrameworkPropertyMetadata(false));
private static DependencyProperty StartPointProperty = DependencyProperty.RegisterAttached(
    "StartPoint", typeof(Point), typeof(Window1), new FrameworkPropertyMetadata(default(Point)));

The whole thing starts when the user presses the mouse button, so let's start our code from there.

private void ListboxPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    ListBox listbox = (ListBox)sender;
    string s = GetBoundItemFromPoint(listbox, e.GetPosition(listbox));
    if (s != null)
    {
        listbox.SetValue(IsDownProperty, true);
        listbox.SetValue(DraggingElementProperty, s);
        listbox.SetValue(StartPointProperty, e.GetPosition(listbox));
    }
}

GetBoundItemFromPoint will be familiar to readers of this blog, although here's a slightly modified version for C# rather than VB.Net.

private string GetBoundItemFromPoint(ListBox box, Point point)
{
    UIElement element = box.InputHitTest(point) as UIElement;
    while (element != null)
    {
        if (element == box)
        {
            return null;
        }
        object item = box.ItemContainerGenerator.ItemFromContainer(element);
        bool itemFound = !object.ReferenceEquals(item, DependencyProperty.UnsetValue);
        if (itemFound)
        {
            return (string)item;
        }
        else
        {
            element = VisualTreeHelper.GetParent(element) as UIElement;
        }
    }
    return null;
}

Now that we've stored all the information about the operation that we're about to start, it's time to see what happens when the user starts to move the mouse with the button pressed.

private void ListboxPreviewMouseMove(object sender, MouseEventArgs e)
{
    ListBox listbox = (ListBox)sender;

    bool isDown = (bool)listbox.GetValue(IsDownProperty);
    if (!isDown)
    {
        return;
    }

    Point startPoint = (Point)listbox.GetValue(StartPointProperty);

    if (Math.Abs(e.GetPosition(listbox).X - startPoint.X) > SystemParameters.MinimumHorizontalDragDistance ||
        Math.Abs(e.GetPosition(listbox).Y - startPoint.Y) > SystemParameters.MinimumVerticalDragDistance)
    {
        DragStarted(listbox);
    }
}

DragStarted will also be familiar to readers - I'm following the same pattern I've done in the past, as user expectations don't vary much in this regard (the actual details of how we choose to determine what to drag and how to move it around do, however).

private void DragStarted(ListBox listbox)
{
    listbox.ClearValue(IsDownProperty); // SetValue to false would also work.

    // Add the bound item, available as DraggingElement, to a DataObject, however we see fit.
    string draggingElement = (string)listbox.GetValue(DraggingElementProperty);
    DataObject d = new DataObject(DataFormats.UnicodeText, draggingElement);
    DragDropEffects effects = DragDrop.DoDragDrop(listbox, d, DragDropEffects.Copy | DragDropEffects.Move);
    if ((effects & DragDropEffects.Move) != 0)
    {
        // Move rather than copy, so we should remove from bound list.
        ObservableCollection<string> collection = (ObservableCollection<string>)listbox.ItemsSource;
        collection.Remove(draggingElement);
    }
}

The Drop case is very simple at this point.

private void ListboxDrop(object sender, DragEventArgs e)
{
    ListBox listbox = (ListBox)sender;
    ObservableCollection<string> collection = (ObservableCollection<string>)listbox.ItemsSource;
    if (e.Data.GetDataPresent(DataFormats.UnicodeText, true))
    {
        collection.Add((string)e.Data.GetData(DataFormats.UnicodeText, true));
        e.Effects =
            ((e.KeyStates & DragDropKeyStates.ControlKey) != 0) ?
            DragDropEffects.Copy : DragDropEffects.Move;
        e.Handled = true;
    }
}

And, of course, we should handle the case where the user clicks but never intends to drag anything.

private void ListboxPreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    ListBox listbox = (ListBox)sender;
    listbox.ClearValue(IsDownProperty);
    listbox.ClearValue(DraggingElementProperty);
    listbox.ClearValue(StartPointProperty);
}

I've purposefully made this interoperable with other progrems, so you can drag and drop strings to and from other programs, including Microsoft Word or Microsoft Visual Studio. If I wanted to keep this just between my programs, I would probably have opted for a custom data format.

In short, this isn't very different from other cases we've seen so far. The interesting bits are updating the collection that the ListBox is bound to, which is something that I've done in a very direct manner for this simple sample, but that wouldn't be too hard to adapt to more generic collections, by using the different binding interfaces that are available.

This posting is provided "AS IS" with no warranties, and confers no rights. Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm.

소스 부분을 그대로 복사 해서 프로젝트를 만들면 2개의 리스트박스에서 Drag&Drop이 되는 모습을 볼 수 있다

Trackback 0 | Comment 1

고독한개발자's Blog is powered by Daum & tistory