728x90
반응형

using System;

using System.Threading;

using System.Threading.Tasks;

 

using Android.Content;

using Android.Webkit;

 

using AUOSMS.APP.Controls;

using AUOSMS.APP.Droid.Renderers;

 

using Xamarin.Forms;

using Xamarin.Forms.Platform.Android;

 

[assembly: ExportRenderer(typeof(WebViewer), typeof(WebViewRender))]

namespace AUOSMS.APP.Droid.Renderers

{

    public class WebViewRender : WebViewRenderer

    {

        public WebViewRender(Context context) : base(context)

        { }

 

        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)

        {

            base.OnElementChanged(e);

 

            if (Control == null) return;

 

            // Cache Clear

            Control.ClearCache(true);

            Control.Settings.SetAppCacheEnabled(false);

            Control.Settings.CacheMode = Android.Webkit.CacheModes.NoCache;

 

            // JavaScript 허용

            Control.Settings.JavaScriptEnabled = true;

 

            // Cookie 허용

            CookieManager cookieManager = CookieManager.Instance;

            cookieManager.SetAcceptCookie(true);

            cookieManager.SetAcceptThirdPartyCookies(Control, true);

        }

    }

}

 

* 참고링크

https://stackoverflow.com/questions/42853636/put-cookie-on-a-webview-in-xamarin/42854428

 

* 참고지식 - Android 기준

mixedContentMode

혼합 컨텐츠 모드를 지정합니다. 즉, WebView를 사용하면 안전한 출처가 다른 출처의 콘텐츠를로드 할 수 있습니다.

never (기본값) : WebView는 보안 오리진이 안전하지 않은 오리진에서 컨텐츠를로드하도록 허용하지 않습니다.

always : WebView를 사용하면 보안 출처가 다른 출처에서 콘텐츠를로드 할 수 있습니다 (해당 출처가 안전하지 않은 경우에도).

compatibility : WebView는 혼합 컨텐츠와 관련하여 최신 웹 브라우저의 접근 방식과 호환되도록 시도합니다.

 

 

thirdPartyCookiesEnabled

WebView 에서 타사 쿠키를 활성화하는 부울 값입니다. Android Kitkat 이상 및 iOS에서 타사 쿠키가 기본적으로 활성화 된 경우에만 Android Lollipop 이상에서 사용됩니다.

기본값은 true 입니다.

 

 

 

728x90
반응형
728x90
반응형
/// <summary>
/// Random Color
/// </summary>
/// <returns></returns>
private Brush RandomBrush()
{
    Brush result = Brushes.Transparent;

    Random random = new Random();

    Type brushesType = typeof(Brushes);

    PropertyInfo[] properties = brushesType.GetProperties();

    int randomValue = random.Next(properties.Length);
    result = (Brush)properties[randomValue].GetValue(null, null);

    return result;
}

 

728x90
반응형
728x90
반응형

UpdateSourceTrigger 속성은 바인딩 소스 업데이트 타이밍을 결정하는 값을 가져오거나 설정할때 사용되는 속성입니다.

 

Default

Text속성의 기본값은 LostFocus이지만, 대부분의 종속성 속성의 기본값은 PropertyChanged입니다.

 

PropertyChanged

바인딩 대상 속성이 변경될 때마다 바인딩 소스를 즉시 업데이트합니다.

 

LostFocus

바인딩 대상 요소가 포커스를 잃을 때마다 바인딩 소스를 업데이트합니다.

 

Explicit

UpdateSource 메서드를 호출할 때만 바인딩 소스를 업데이트합니다.


예)

 BindingExpression bindingExpression = textBox.GetBindingExpression(TextBox.TextProperty);

 bindingExpression.UpdateSource();


 

 

* 간단히 말하면 커서가 벗어난 경우(LostFocus) 속성변경 처리를 할것이냐 아니면 실시간으로(PropertyChanged) 반영할것이냐라고 보면 될것같습니다.

 

아래는 간단한 예시입니다.

 

MainWindow.xaml

<Window x:Class="UpdateSourceTriggerTest.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

        mc:Ignorable="d"

        Title="MainWindow" Height="190" Width="394.666">

    <Grid>

        <StackPanel>

            <Label Content="UpdateSourceTrigger=PropertyChanged"/>

            <TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"/>

            

            <Rectangle StrokeThickness="1" Fill="#465168" Height="1" />

            <Label Content=" UpdateSourceTrigger=Default"/>

            <TextBox Text="{Binding Name, UpdateSourceTrigger=Default}"/>

 

            <Rectangle StrokeThickness="1" Fill="#465168" Height="1" />

            <Label Content=" Value"/>

            <Label Content="{Binding Name}"/>

        </StackPanel>

    </Grid>

</Window>

 

 

MainWindow.xaml.cs

using System.Windows;

 

namespace UpdateSourceTriggerTest

{

    /// <summary>

    /// MainWindow.xaml에 대한 상호 작용 논리

    /// </summary>

    public partial class MainWindow : Window

    {

        public MainWindow()

        {

            InitializeComponent();

 

            this.DataContext = new TestData() { Name = "TEST", Order = 1 };

        }

 

        public class TestData

        {

            public string Name { get; set; }

            public int Order { get; set; }

        }

    }

}

 

 


 

예시를 보면

PropertyChanged 인 경우는 실시간으로 변경사항이 반영되지만

Default 인 경우는 커서를 벗어난 경우 변경사항이 반영됩니다.

상황에 따라 맞는걸 쓰면 되겠습니다.

 

 

728x90
반응형
728x90
반응형

테스트박스가 비어있을 때 특정한 텍스트를 표시 하고 싶을때 사용합니다

("조회할 값을 입력해 주세요" 등..)

<Window x:Class="PlaceHolder.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

        mc:Ignorable="d"

        Title="MainWindow" Height="86.638" Width="227.155">

    <StackPanel>

        <Grid>

            <TextBox Name="searchTextBox" Margin="10"  Text="" Width="180" Height="32" HorizontalAlignment="Left" VerticalAlignment="Center" VerticalContentAlignment="Center"/>

            <TextBlock Text="Search Name.." IsHitTestVisible="False" VerticalAlignment="Center" Margin="15,10,10,10" HorizontalAlignment="Left">

                <TextBlock.Style>

                    <Style TargetType="TextBlock">

                        <Setter Property="Visibility" Value="Hidden"/>

                        <Setter Property="Foreground" Value="Gray"/>

                        <Style.Triggers>

                            <DataTrigger Binding="{Binding Text, ElementName=searchTextBox}" Value="">

                                <Setter Property="Visibility" Value="Visible"/>

                            </DataTrigger>

                        </Style.Triggers>

                    </Style>

                </TextBlock.Style>

            </TextBlock>

        </Grid>

    </StackPanel>

</Window>



728x90
반응형
728x90
반응형

Command 에 인자로 두가지 항목을 던지고자 할때

이를 class 로 정의하여 CommandParameter 로 던질수 있다.

 

먼저 프로젝트에 Prism.Wpf Nuget Package 를 설치한다.

 

이제 Class 구조를 잡는다.

(string, object 로 구성)

[StringObject.cs]

namespace MultiValueConverterSample

{

    public class StringObject

    {

        /// <summary>

        /// 문자열 데이터입니다.

        /// </summary>

        public string StringData;

 

        /// <summary>

        /// 오브젝트 데이터입니다.

        /// </summary>

        public object ObjectData;

 

        /// <summary>

        /// 생성자입니다.

        /// </summary>

        /// <param name="stringData">문자열 데이터입니다.</param>

        /// <param name="objectData">오브젝트 데이터입니다.</param>

        public StringObject(string stringData, object objectData)

        {

            this.StringData = stringData;

            this.ObjectData = objectData;

        }

    }

}

 

 

IMultiValueConverter 를 정의한다.

(화면에서 처리된 두개의 인자를 가지고 위에서 만들 Class 구조로 변환해 리턴)

[StringObjectConverter.cs]

using System;

using System.Globalization;

using System.Windows.Data;

 

namespace MultiValueConverterSample

{

    public class StringObjectConverter : IMultiValueConverter

    {

        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)

        {

            return new StringObject(values[0].ToString(), values[1]);

        }

 

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)

        {

            throw new NotImplementedException();

        }

    }

}

 

 

화면에 아래 처럼 구성한다.

(조회 버튼을 클릭하면 StringObjectCommand 를 실행해

입력한 값을 string 으로 버튼 객체를 object 로 하여 CommandParameter 로 사용한다.)

[MainWindow.xaml]

<Window x:Class="MultiValueConverterSample.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

        xmlns:local="clr-namespace:MultiValueConverterSample"

        mc:Ignorable="d"

        Title="MainWindow" Height="450" Width="800">

    <Window.Resources>

        <local:StringObjectConverter x:Key="StringObjectConverter" />

    </Window.Resources>

    <Grid>

        <StackPanel>

            <TextBox Name="contentTextBlock" Width="100" Height="30" Margin="10"/>

            <Button Name="searchButton" Content="조회" Margin="10" Height="30" Width="100" Command="{Binding StringObjectCommand}">

                <Button.CommandParameter>

                    <MultiBinding Converter="{StaticResource StringObjectConverter}">

                        <Binding ElementName="contentTextBlock" Path="Text" />

                        <Binding ElementName="searchButton" />

                    </MultiBinding>

                </Button.CommandParameter>

            </Button>

        </StackPanel>

    </Grid>

</Window>

 

 

코드비하인드 단에서는 아래 처럼 처리한다.

(반드시 this.DataContext = this; 을 해야 Command 가 처리된다.)

[MainWindow.xaml.cs]

using Prism.Commands;

 

using System.Windows;

using System.Windows.Input;

 

namespace MultiValueConverterSample

{

    /// <summary>

    /// MainWindow.xaml에 대한 상호 작용 논리

    /// </summary>

    public partial class MainWindow : Window

    {

        #region StringObjectCommand

 

        /// <summary>

        /// StringObjectCommand

        /// </summary>

        public ICommand StringObjectCommand

        {

            get

            {

                if (stringObjectCommand == null)

                {

                    stringObjectCommand = new DelegateCommand<StringObject>((stringObject) =>

                    {

                        string stringData = stringObject.StringData;

                        object objectData = stringObject.ObjectData;

                    });

                }

                return stringObjectCommand;

            }

        }

        private DelegateCommand<StringObject> stringObjectCommand;

 

        #endregion

 

        public MainWindow()

        {

            InitializeComponent();

 

            this.DataContext = this;

        }

    }

}

 

 

 

조회 버튼을 누르게 되면 Command 에서 아래 처럼 해당 항목이 넘어온것을 확인할 수 있다.

 

 

 

728x90
반응형
728x90
반응형

아래 예시는 각기 다른 4가지 이미지를 4분면에 그리는 코드입니다.

 

4분면에 이미지를 하나씩 그리는 예시입니다.

처음 이미지의 크기에 따라 나머지 이미지 들도 크기가 지정되며

바둑판모양으로 이미지가 달라 붙습니다.

 

        private void MergeImage(string path1, string path2, string path3, string path4, string outputFilePath)

        {

            // 이미지를 로드합니다.

            BitmapFrame frame1 = BitmapDecoder.Create(new Uri(path1), BitmapCreateOptions.None, BitmapCacheOption.OnLoad).Frames.First();

            BitmapFrame frame2 = BitmapDecoder.Create(new Uri(path2), BitmapCreateOptions.None, BitmapCacheOption.OnLoad).Frames.First();

            BitmapFrame frame3 = BitmapDecoder.Create(new Uri(path3), BitmapCreateOptions.None, BitmapCacheOption.OnLoad).Frames.First();

            BitmapFrame frame4 = BitmapDecoder.Create(new Uri(path4), BitmapCreateOptions.None, BitmapCacheOption.OnLoad).Frames.First();

 

            // 첫번째이미지 기준으로 그려질 이미지의 크기를 정의합니다.

            int imageWidth = frame1.PixelWidth;

            int imageHeight = frame1.PixelHeight;

 

            // DrawingVisual 에 전체 4분면에서 각 분면 이미지를 그립니다.

            DrawingVisual drawingVisual = new DrawingVisual();

            using (DrawingContext drawingContext = drawingVisual.RenderOpen())

            {

                drawingContext.DrawImage(frame1, new Rect(0, 0, imageWidth, imageHeight));

                drawingContext.DrawImage(frame2, new Rect(imageWidth, 0, imageWidth, imageHeight));

                drawingContext.DrawImage(frame3, new Rect(0, imageHeight, imageWidth, imageHeight));

                drawingContext.DrawImage(frame4, new Rect(imageWidth, imageHeight, imageWidth, imageHeight));

            }

 

            // RenderTargetBitmap 을 사용해 DrawingVisual 을 BitmapSource 객체로 변환합니다.

            RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap(imageWidth * 2, imageHeight * 2, 96, 96, PixelFormats.Pbgra32);

            renderTargetBitmap.Render(drawingVisual);

 

            // BitmapSource 를 PngBitmapEncoder 를 사용해 frame 에 추가합니다.

            PngBitmapEncoder encoder = new PngBitmapEncoder();

            encoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap));

 

            // 이미지를 저장합니다.

            using (Stream stream = File.Create(outputFilePath))

            {

                encoder.Save(stream);

            }

        }

 

* ico 파일 지정도 가능

 

결과

728x90
반응형
728x90
반응형

Image 를 사용할때 코드 상에서 이미지 경로를 지정 할때

아래 처럼 사용합니다.

 

 

BitmapImage result = new BitmapImage();

result.BeginInit();

result.UriSource = new Uri(@"C:\Users\my\Desktop\100.PNG");

result.EndInit();

 

// Image control

this.resultImage.Source = result;

 

 

728x90
반응형
728x90
반응형

1. Self

{Binding RelativeSource={RelativeSource Self}, Path=Height}

: 자기 자신을 참조하는 것으로 위 내용은 자기 자신의 Height 값을 바인딩합니다.

 

2. FindAncestor

{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Border}, AncestorLevel=2},Path=Name}

: 부모를 찾아 바인딩하는 것으로 위 내용은 부모 중 Border 타입을 찾는데 2번째 부모를 찾아 Name 값을 바인딩합니다. (1이면 Border 타입중 바로 자기 상위 부모를 찾습니다.)

 

3. TemplatedParent

<Ellipse Height="100" Width="150" Fill="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background}"/>

: 위 항목이 Style 에 정의 되어있는 경우 해당 Style 을 사용하는 항목의 요소를 변경한다.

  위내용은 원을 그릴때 해당 Style 를 사용하는 컨트롤의 BackGround 색으로 원을 체웁니다.

 

4. PreviousData

{Binding RelativeSource={RelativeSource PreviousData},Path=Value}

: 이전값을 가지는 것으로 위 내용은 이전 값의 Value 값을 바인딩 합니다.

 

 

참고 : https://www.c-sharpcorner.com/UploadFile/yougerthen/relativesources-in-wpf/

 

아래는 백업 용도 ---

 

A lot of articles those are talking about binding and sources, and how to bind properties each other using StaticResources, DynamicResources, although you can find information about the RelativeSource and its use cases but not with more details even in Microsoft documentations. In this article, I will expose the use cases of the RelativeSources in WPF.

The RelativeSource is a markup extension that is used in particular binding cases when we try to bind a property of a given object to another property of the object itself, when we try to bind a property of a object to another one of its relative parents, when binding a dependency property value to a piece of XAML in case of custom control development and finally in case of using a differential of a series of a bound data. All of those situations are expressed as relative source modes. I will expose all of those cases one by one.

1. Mode Self:

Imagine this case, a rectangle that we want that its height is always equal to its width, a square let's say. We can do this using the element name

<Rectangle Fill="Red" Name="rectangle"
                   
 Height="100" Stroke="Black"
                   
 Canvas.Top="100" Canvas.Left="100"
                    Width="{Binding ElementName=rectangle,
                    Path=Height}"/>

But in this above case we are obliged to indicate the name of the binding object, namely the rectangle. We can reach the same purpose differently using the RelativeSource

<Rectangle Fill="Red" Height="100"
                  
 Stroke="Black"
                  
 Width="{Binding RelativeSource={RelativeSource Self},
                   Path=Height}"/>

For that case we are not obliged to mention the name of the binding object and the Width will be always equal to the Height whenever the height is changed.

If you want to parameter the Width to be the half of the height then you can do this by adding a converter to the Binding markup extension.
Let's imagine another case now:

 <TextBlock Width="{Binding RelativeSource={RelativeSource Self},
                   Path=Parent.ActualWidth}"/>

The above case is used to tie a given property of a given element to one of its direct parent ones as this element holds a property that is called Parent. This leads us to another relative source mode which is the FindAncestor one.

2. Mode FindAncestor

In this case, a property of a given element will be tied to one of its parents, Of Corse. The main difference with the above case is the fact that, it's up to you to determine the ancestor type and the ancestor rank in the hierarchy to tie the property. By the way try to play with this piece of XAML

<Canvas Name="Parent0">
        <Border Name="Parent1"
                 Width="{Binding RelativeSource={RelativeSource Self},
                 Path=Parent.ActualWidth}"
                 Height="{Binding RelativeSource={RelativeSource Self},
                 Path=Parent.ActualHeight}">
            <Canvas Name="Parent2">
                <Border Name="Parent3"
                Width="{Binding RelativeSource={RelativeSource Self},
               Path=Parent.ActualWidth}"
               Height="{Binding RelativeSource={RelativeSource Self},
                  Path=Parent.ActualHeight}">
                   <Canvas Name="Parent4">
                   <
TextBlock FontSize="16"
                   Margin="5" Text="Display the name of the ancestor"/>
                   <TextBlock FontSize="16"
                     
Margin="50"
                
Text="{Binding RelativeSource={RelativeSource 
                           FindAncestor
,
                           
AncestorType={x:Type Border},
                           AncestorLevel=2},Path=Name}"
                           
Width="200"/>
                    </Canvas>
                </Border>
            </Canvas>
        </Border>
    </Canvas>

The above situation is of two TextBlock elements those are embedded within a series of borders and canvas elements those represent their hierarchical parents. The second TextBlock will display the name of the given parent at the relative source level.

So try to change AncestorLevel=2 to AncestorLevel=1 and see what happens. Then try to change the type of the ancestor from AncestorType=Border to AncestorType=Canvas and see what's happens.

The displayed text will change according to the Ancestor type and level. Then what's happen if the ancestor level is not suitable to the ancestor type? This is a good question, I know that you're about to ask it. The response is no exceptions will be thrown and nothings will be displayed at the TextBlock level.

3. TemplatedParent

This mode enables tie a given ControlTemplate property to a property of the control that the ControlTemplate is applied to. To well understand the issue here is an example bellow

<Window.Resources>
    <ControlTemplate x:Key="template">
            <Canvas>
                <Canvas.RenderTransform>
                    <RotateTransform Angle="20"/>
                    </Canvas.RenderTransform>
                <Ellipse Height="100" Width="150"
                    
 Fill="{Binding
               
 RelativeSource={RelativeSource TemplatedParent},
                Path=Background}">

                  </Ellipse>
                <ContentPresenter Margin="35"
                      Content
="{Binding RelativeSource={RelativeSource 
                      TemplatedParent
},Path=Content}"/>
            </Canvas>
        </ControlTemplate>
    </Window.Resources>
        <Canvas Name="Parent0">
        <Button   Margin="50"
                  Template
="{StaticResource template}" Height="0"
                  Canvas.Left
="0" Canvas.Top="0" Width="0">
            <TextBlock FontSize="22">Click me</TextBlock>
        </Button>
    </Canvas>

If I want to apply the properties of a given control to its control template then I can use the TemplatedParent mode. There is also a similar one to this markup extension which is the TemplateBinding which is a kind of short hand of the first one, but the TemplateBinding is evaluated at compile time at the contrast of the TemplatedParent which is evaluated just after the first run time. As you can remark in the bellow figure, the background and the content are applied from within the button to the control template.



4. PreviousData

This is the most ambiguous and the less used mode of the RelativeSource, I mean the PreviousData one. The PreviousData is used for particular cases. Its purpose is to tie the given property to another property with a particular assignment; I mean it assigns the previous value of the property to the bound one. In other word, if you have a TextBox that has a text property and another control that has a value property that holds data. Say that value is actually 5 and it was 3 just before. The 3 is assigned to the text property of the TextBox and not 5. This leads to the idea that this kind of RelativeSource is frequently used with the items controls.

To understand the phenomenon of the RelativeSource let's expose this sample. I will add an ItemsControl into the scene and I will aliment it from a custom collection

<Grid>
    <ItemsControl></ItemsControl>
</
Grid>

This ItemsControl is alimented using this collection:

public class Items : ObservableCollection<Item>
    {
        
public Items()
        {
            Add(
new Item { Value = 80.23 });
            Add(
new Item { Value = 126.17 });
            Add(
new Item { Value = 130.21 });
            Add(
new Item { Value = 115.28 });
            Add(
new Item { Value = 131.21 });
            Add(
new Item { Value = 135.22 });
            Add(
new Item { Value = 120.27 });
            Add(
new Item { Value = 110.25 });
            Add(
new Item { Value = 90.20 });
        }
    }


It's an ObservableCollection of type Item that I had developed and that holds a simple property which is called Value, it is of type double.

 
public class Item :INotifyPropertyChanged
    {
        
private double _value;

        public double Value
        {
            
get { return _value; }
            
set { _value = value; OnPropertyChanged("Value"); }
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

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

Now, to bind the 
ItemsControl to the collection data, I will set the DataContext property of the whole window to the collection at the Window constructor level.

 public Window1()

        {

            InitializeComponent();

            this.DataContext = new Items();

        }

And then I'll specify the binding of the ItemsControl

ItemsControl ItemsSource="{Binding}" Margin="10"

Then the result will be like this. I mean not presentable.



Therefore, we have to apply some features to enhance the visual of that representation.

<ItemsControl ItemsSource="{Binding}" Margin="10">

        <ItemsControl.ItemsPanel>
           <ItemsPanelTemplate>
              <StackPanel Orientation="Horizontal"/>
           </ItemsPanelTemplate>
           </ItemsControl.ItemsPanel>
       <ItemsControl.ItemTemplate>
          <DataTemplate>
              <StackPanel>
             <Border CornerRadius="3" BorderThickness="3"
                Width
="80" Height="{Binding Value}"
                            Margin
="0,0,35,0" 
                           
 BorderBrush="Violet" 
                            Background
="BlueViolet">
                            <TextBlock Text="{Binding Value}"
                               FontWeight
="bold"
                               VerticalAlignment
="Center"
                               
HorizontalAlignment="Center" 
                               Foreground
="Wheat">
                        <TextBlock.RenderTransform>
                  <TransformGroup>
                            <ScaleTransform ScaleY="-1"/>
                 
</TransformGroup>
                  </TextBlock.RenderTransform>
                  </TextBlock>
             </Border>
         </StackPanel>
      </DataTemplate>
   </ItemsControl.ItemTemplate>
   <
ItemsControl.RenderTransform>
       <TransformGroup>
         <ScaleTransform ScaleY="-1"/>
         <TranslateTransform Y="250"/>
       </TransformGroup>
   </ItemsControl.RenderTransform>
 </ItemsControl>


Shortly, I will describe the above XAML. First, the ItemsPanel will arrange the items within an horizontal StackPanel for more information about the ItemsPanel please refer to this link

http://msdn.microsoft.com/en-us/library/system.windows.controls.itemscontrol.itemspanel.aspx


Second, the DataTemplate is used to present the data as a border; the border height is bound to the Value of the item class to reflect the Values that the collection holds. The same border includes a TextBlock that displays the Value of the Item object.

For more information about te DateTemplate please refer to this MSDN link

http://msdn.microsoft.com/en-us/library/system.windows.datatemplate.aspx



The RenderTransform is used to emphasize the position of the items in the scene. For more information about transformation please refer to this MSDN link

http://msdn.microsoft.com/en-us/library/system.windows.media.transform.aspx


The result of the presentation will be as follow



Now, the main purpose of this demo is to show the characteristic of the RelativeSource.PreviousData mode.

The idea consists of adding a TextBox and tie the Text property to the Value of the previous border in the items' list. Something that seems to be as the bellow representation



As you can note, each TextBlock represents the previous value that the previous item holds. This is in fact the magic of the PreviousData of the RelativeSource mode.

The idea is to add the TextBlock to the DataTemplate as Follow

<TextBlock FontSize="14" FontWeight="bold" Margin="20"
            
Text="{Binding RelativeSource={RelativeSource PreviousData},
                   Path
=Value}">
                          <TextBlock.RenderTransform>
                              <ScaleTransform ScaleY="-1"/>
                          </TextBlock.RenderTransform>   
</TextBlock>

Then the whole picture will be

<Grid>
    <ItemsControl ItemsSource="{Binding}" Margin="10">
        <ItemsControl.RenderTransform>
            <TransformGroup>
                <ScaleTransform ScaleY="-1"/>
                <TranslateTransform Y="250"/>
            </TransformGroup>
        </ItemsControl.RenderTransform>
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Horizontal"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBlock FontSize="14" FontWeight="bold"
                           Margin
="20"
                           
Text="{Binding
                           RelativeSource
={RelativeSource PreviousData},
                                               Path
=Value}">
                      <TextBlock.RenderTransform>
                          <ScaleTransform ScaleY="-1"/>
                      </TextBlock.RenderTransform>   
                    
</TextBlock>
                    <Border CornerRadius="3" BorderThickness="3"
                           Width
="80" Height="{Binding Value}"
                           Margin
="0,0,35,0" 
                       
 BorderBrush="Violet" Background="BlueViolet">
                        <TextBlock Text="{Binding Value}"
                           FontWeight
="bold" VerticalAlignment="Center"
                                  
 HorizontalAlignment="Center"
                                   Foreground
="Wheat">
                        <TextBlock.RenderTransform>
                            <TransformGroup>
                        <ScaleTransform ScaleY="-1"/>
                        
</TransformGroup>
                        </TextBlock.RenderTransform>
                        </TextBlock>
                    </Border>
                </StackPanel>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</
Grid>

Of Course, we could do more that this using RelativeSource.PreviousData but this will be enough to have a general consistent idea about that mode. That's all

728x90
반응형
728x90
반응형

DrawingBrush 를 이용하여 체스판을 만들어 봅니다.

체스판의 한 조각을 만들어 이어 붙이는 예제입니다.

 

한조각은 아래 그림과 같으며

 

 

DrawingBrush 의 Viewport 와 TileMode 를 이용해 이어붙여 체스판을 완성합니다.

 

MainWindow.xaml.cs

        private void CreateChessBoardWithDrawingBrush()

        {

            // 반복하여 그려질 사각형의 바탕이 되는 흰색배경의 사각형을 만듭니다.

            GeometryDrawing whiteRectDrawing = new GeometryDrawing(Brushes.White, null, new RectangleGeometry(new Rect(0, 0, 400, 400)));

 

            // 검은색으로 채울 사각형을 정의합니다.

            GeometryGroup blackGeometryGroup = new GeometryGroup();

            blackGeometryGroup.Children.Add(new RectangleGeometry(new Rect(0, 0, 200, 200)));

            blackGeometryGroup.Children.Add(new RectangleGeometry(new Rect(200, 200, 200, 200)));

 

            // 정의한 사격형을 검은색으로 체웁니다.

            GeometryDrawing blackRectDrawing = new GeometryDrawing(new SolidColorBrush(Colors.Black), null, blackGeometryGroup);

 

            // 배경에 해당하는 흰색 사각형과 체크표시할 검은색 사각형을 그룹으로 묶습니다.

            DrawingGroup checkersDrawingGroup = new DrawingGroup();

            checkersDrawingGroup.Children.Add(whiteRectDrawing);

            checkersDrawingGroup.Children.Add(blackRectDrawing);

 

            // DrawingGroup 를 요소로 가지는 DrawingBrush 를 정의합니다.

            DrawingBrush chessBrush = new DrawingBrush() { Drawing = checkersDrawingGroup };

 

            // DrawingGroup 의 Viewport 와  TileMode 를 정의합니다.

            chessBrush.Viewport = new Rect(0, 0, 0.25, 0.25); // 1 기준으로 0.25 인경우 4칸.4줄로 나눠집니다.

            chessBrush.TileMode = TileMode.Tile;

 

            // 큰 사각형을 정의하여 DrawingBrush 로 내부를 그리도록 합니다.

            Rectangle chessRectangle = new Rectangle();

            chessRectangle.Width = 300;

            chessRectangle.Height = 300;

            chessRectangle.Fill = chessBrush;

 

            Content = chessRectangle;

        }

 

결과

 

 

 

 

728x90
반응형
728x90
반응형

마우스 드래그시 사각형을 그리고 사각형 주변으로 길이를 표시합니다.

 

MainWindow.xaml

<Window x:Class="WpfApp.MainWindow"

        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:local="clr-namespace:WpfApp"

        mc:Ignorable="d"

        Title="MainWindow" Height="450" Width="800" Background="Gray">

    <Grid Background="#01000000">

        <Canvas IsHitTestVisible="False" IsEnabled="False">

            <!-- Rectangle -->

            <ContentControl x:Name="RectAdder" Visibility="Collapsed">

                <ContentControl.ContentTemplate>

                    <DataTemplate>

                        <Grid >

                            <Rectangle

                                x:Name="Rect" SnapsToDevicePixels="True"

                                Fill="#770000FF" Stroke="White" StrokeThickness="1" StrokeDashArray="1 1 1 3" />

                            <!--위쪽-->

                            <Grid x:Name="DrawingHSizeAdorner">

                                <Rectangle

                                    Width="1" Height="15" Fill="White" SnapsToDevicePixels="True"

                                    IsHitTestVisible="False" IsEnabled="False"

                                    HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,-18,0,0"

                                    Tag="TopLeft"/>

                                <Rectangle

                                    Height="1" Width="{Binding ActualWidth, ElementName=Rect}"

                                    Fill="White" SnapsToDevicePixels="True"

                                    IsHitTestVisible="False" IsEnabled="False"

                                    HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0,-10,0,0"

                                    Tag="TopCenter"/>

                                <Rectangle

                                    Width="1" Height="15" Fill="White" SnapsToDevicePixels="True"

                                    IsHitTestVisible="False" IsEnabled="False"

                                    HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,-18,0,0"

                                    Tag="TopRight"/>

                                <TextBlock

                                    Text="{Binding ActualWidth, ElementName=Rect, StringFormat='0.00 mm'}" Height="15" Width="{Binding ActualWidth, ElementName=Rect}"

                                    SnapsToDevicePixels="True" IsHitTestVisible="False" IsEnabled="False"

                                    HorizontalAlignment="Center" VerticalAlignment="Top"

                                    TextAlignment="Center" Foreground="White" FontSize="9"

                                    Margin="0,-25,0,0"

                                    ClipToBounds ="True"/>

                            </Grid>

                            <!--아래쪽-->

                            <Grid x:Name="DrawingBHSizeAdorner" >

                                <Rectangle

                                    Width="1" Height="15" Fill="White" SnapsToDevicePixels="True"

                                    IsHitTestVisible="False" IsEnabled="False"

                                    HorizontalAlignment="Left" VerticalAlignment="Bottom"

                                    Margin="0,0,0,-18"

                                    Tag="BottomLeft"/>

                                <Rectangle

                                    Height="1" Width="{Binding ActualWidth, ElementName=Rect}"

                                    Fill="White" SnapsToDevicePixels="True"

                                    IsHitTestVisible="False" IsEnabled="False"

                                    HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,0,0,-10"

                                    Tag="BottomCenter"/>

                                <Rectangle

                                    Width="1" Height="15" Fill="White" SnapsToDevicePixels="True"

                                    IsHitTestVisible="False" IsEnabled="False"

                                    HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,0,-18"

                                    Tag="BottomRight"/>

                                <TextBlock

                                    Text="{Binding ActualWidth, ElementName=Rect, StringFormat='0.00 mm'}" Height="15" Width="{Binding ActualWidth, ElementName=Rect}"

                                    SnapsToDevicePixels="True" IsHitTestVisible="False" IsEnabled="False"

                                    HorizontalAlignment="Center" VerticalAlignment="Bottom"

                                    TextAlignment="Center" Foreground="White" FontSize="9"

                                    Margin="0,0,0,-25"

                                    ClipToBounds ="True"/>

                            </Grid>

                            <!--왼쪽-->

                            <Grid x:Name="DrawingLVSizeAdorner" Margin="10,0,0,0">

                                <Rectangle Width="15" Height="1" Fill="White" SnapsToDevicePixels="True"

                                           IsHitTestVisible="False" IsEnabled="False"

                                           HorizontalAlignment="Left"

                                           VerticalAlignment="Top"

                                           Margin="-27,0,0,0"

                                           Tag="LeftTop"/>

                                <Rectangle Height="{Binding ActualHeight, ElementName=Rect}" Width="1" Fill="White" SnapsToDevicePixels="True"

                                           IsHitTestVisible="False" IsEnabled="False"

                                           HorizontalAlignment="Left" VerticalAlignment="Center" Margin="-20,0,0,0"

                                           Tag="LeftCenter"/>

                                <Rectangle Width="15" Height="1" Fill="White" SnapsToDevicePixels="True"

                                           IsHitTestVisible="False" IsEnabled="False"

                                           HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="-27,0,0,0"

                                           Tag="LeftBottom"/>

                                <StackPanel Margin="-35,70,0,0" HorizontalAlignment="Left" Height="25"

                                            SnapsToDevicePixels="True" IsHitTestVisible="False" IsEnabled="False"

                                            VerticalAlignment="Center">

                                    <StackPanel.RenderTransform>

                                        <RotateTransform Angle="270"/>

                                    </StackPanel.RenderTransform>

                                    <TextBlock Text="{Binding ActualHeight, ElementName=Rect, StringFormat='0.00 mm'}" Height="25" Foreground="White" FontSize="9"/>

                                </StackPanel>

                            </Grid>

                            <!--오른쪽-->

                            <Grid x:Name="DrawingVSizeAdorner" Margin="10,0,0,0">

                                <Rectangle

                                    Width="15" Height="1" Fill="White" SnapsToDevicePixels="True"

                                    IsHitTestVisible="False" IsEnabled="False"

                                    HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,0,-18,0"

                                    Tag="RightTop"/>

                                <Rectangle Height="{Binding ActualHeight, ElementName=Rect}" Width="1" Fill="White" SnapsToDevicePixels="True"

                                           IsHitTestVisible="False" IsEnabled="False"

                                           HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,-11,0"

                                           Tag="RightCenter"/>

                                <Rectangle Width="15" Height="1" Fill="White" SnapsToDevicePixels="True"

                                           IsHitTestVisible="False" IsEnabled="False"

                                           HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,-18,0"

                                           Tag="RightBottom"/>

                                <StackPanel Margin="0,0,-70,0" HorizontalAlignment="Right" Height="25"

                                            SnapsToDevicePixels="True" IsHitTestVisible="False" IsEnabled="False"

                                            VerticalAlignment="Center">

                                    <StackPanel.RenderTransform>

                                        <RotateTransform Angle="90"/>

                                    </StackPanel.RenderTransform>

                                    <TextBlock Text="{Binding ActualHeight, ElementName=Rect, StringFormat='0.00 mm'}" Height="25" Foreground="White" FontSize="9"/>

                                </StackPanel>

                            </Grid>

                            <TextBlock Text="+" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" />

                        </Grid>

                    </DataTemplate>

                </ContentControl.ContentTemplate>

            </ContentControl>

        </Canvas>

    </Grid>

</Window>

 

 

MainWindow.xaml.cs

using System;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Input;

 

namespace WpfApp

{

    /// <summary>

    /// MainWindow.xaml에 대한 상호 작용 논리

    /// </summary>

    public partial class MainWindow : Window

    {

        /// <summary>

        /// 좌측 마우스 클릭 시 포인트 위치입니다.

        /// </summary>

        Point? downPoint;

 

        /// <summary>

        /// 그려질 사각형입니다.

        /// </summary>

        Rect addRect;

 

        public MainWindow()

        {

            InitializeComponent();

        }

 

        /// <summary>

        /// 마우스 좌측 버튼 클릭 시 이벤트입니다.

        /// </summary>

        /// <param name="e"></param>

        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)

        {

            var pos = e.GetPosition(this);

            downPoint = pos;

 

            this.CaptureMouse();

        }

 

        /// <summary>

        /// 마우스 이동 시 이벤트입니다.

        /// </summary>

        /// <param name="e"></param>

        protected override void OnPreviewMouseMove(MouseEventArgs e)

        {

            base.OnPreviewMouseMove(e);

 

            if (Mouse.LeftButton == MouseButtonState.Pressed)

            {

                var pos = e.GetPosition(this);

 

                this.RectAdder.Visibility = Visibility.Visible;

 

                this.addRect = new Rect(new Point(downPoint.Value.X, downPoint.Value.Y), new Point(pos.X, pos.Y));

 

                Canvas.SetLeft(this.RectAdder, this.addRect.X);

                Canvas.SetTop(this.RectAdder, this.addRect.Y);

                this.RectAdder.Width = Math.Abs(this.addRect.Width);

                this.RectAdder.Height = Math.Abs(this.addRect.Height);

            }

        }

 

        /// <summary>

        /// 마우스를 놓을때 발생되는 이벤트입니다.

        /// </summary>

        /// <param name="e"></param>

        protected override void OnMouseUp(MouseButtonEventArgs e)

        {

            this.ReleaseMouseCapture();

        }

    }

}

 

 

 


728x90
반응형

+ Recent posts