노무현 전 대통령 서거 - 삼가 고인의 명복을 빕니다
WPF - 해당되는 글 5건
 
(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: }
Trackbacks 0 | Comments 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이 되는 모습을 볼 수 있다

Trackbacks 0 | Comments 1

ComboBoxItem으로 Item을 추가 한경우

private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
            ComboBox a = sender as ComboBox;
            
            ComboBoxItem c = a.SelectedItem as ComboBoxItem;

            string selected_text = c.Content;           
 }
 

비하인트 코드로 Item을 추가한경우 ex) comboBox1.Items.Add(" temp_item ");

private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ComboBox a = sender as ComboBox;

string selected_text = a.SelectedValue.ToString();
}
Trackbacks 0 | Comments 0
이번에는 WinForm에서 WPF Dialog를 띠우는 방법이다.  WPF에서 Window UserContlor을 호스팅해서 사용하게 되었다. 하지만 문제가 생긴것은 호스팅되어 사용하려고 한 Window UserContlor컨트롤에서 Dialog를 호출할때 생겼다.  결론만 말하자면 WPF에서 Form(WindowsForm)을 그냥 생성해서 부르는 꼴이 되어버려서 호출할때 오류를 발생 시켰다.


그래서 역으로 생각해 WindowsForm에서 WPF(Windows)를 호출하는 방법을 택했다.
※ 문제는의 원인은 WindowsForm과 WPF는 관리되는 방식이 틀리기 때문이다.




WindowInteropHelper Class(MSDN)
   - WPF(Windows Presentation Foundation)와 Win32 코드 사이의 상호 운용을 지원하는 클레스

< 링크 >




WindowInteropHelper wih = new WindowInteropHelper(myDialog);
wih.Owner = ownerHwnd;   // ownerHwnd는 WinForm의 핸들값을 주는 코와 대체한다.
                                       //  ex) this.Handle; 
myDialog.ShowDialog();   

myDialog는 당연히 WPF로 생성한 객체이다.



- 참고 -
WPF로 객체를 생성하려고 변수 선언을 했을떄 어셈블리 참조가 되어 있지 않다고 에러가 났다. 
그냥 WPF에서 참조 되어있는 모든것을 똑같이 WinForm에서 참조 시켜서 해결했다. - 왼지 미방책인 느낌
Trackbacks 0 | Comments 0
Wpf와 WinForm에서 똑같은 컨트롤들이 존재한다. 하지만 Wpf와 WinForm의 컨틀롤에는 차이가 있기때문에 완전히 똑같이 구현하기 힘들 었다. 그래서 찾은 방법이 Wpf에서 WinForm의 컨트롤을 그대로 가져가 사용 하는 방법이다.

WindowsFormsHost Class(MSDN참조)
http://msdn.microsoft.com/ko-kr/library/system.windows.forms.integration.windowsformshost(VS.85).aspx

비하인트 코드에서 Winform 컨트롤 생성방법
  • System.Windows.Forms.Integration을 참조 한다.(WindowsFormsHost 사용을위해)
  • WinForm으로 구현된 프로젝트 또는 코드파일을 추가한다.
  • Wpf프로젝트에서 WinFrom프로젝트(namespace)를 참조한다.

 
         private void TestWinFormControlInWpf_Loaded(object sender, RoutedEventArgs e)  
        {  
            TestWinFromControl.MyControl control = new TestWinFromControl.MyControl();  
 
            WindowsFormsHost host = new WindowsFormsHost();  
            host.Child = control;  
            this.Content = host;  
 
            WindowsFormsHost.EnableWindowsFormsInterop();  
        }  


xaml에서 Winform 컨트롤 생성방법

  • 비하인트 코트 방식 같은 절차를 거친다
  • xmlns 키워드로 컨트롤 어셈블리를 참조한다

 
<Window x:Class="WpfApplication1.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"   
    xmlns:lib="clr-namespace:TestWinFromControl;assembly=TestWinFromControl" 
    Title="Window1" Height="600" Width="600">  
    <Grid> 
         <WindowsFormsHost>  
       <lib:MyControl></lib:MyControl>  
        </WindowsFormsHost>   
 
    </Grid> 
</Window> 

※ WindowsFormsHost또한 도구상자에서 지원하는 컨트롤중에 하나이다. 크기를 정하고 싶다면 속성으로
줄수 있다.


Trackbacks 0 | Comments 0

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