728x90
반응형

Expander 의 Header 를 아래처럼 커스텀 할수 있다.

Download & run this example

<Expander Margin="10">
    <Expander.Header>
<DockPanel VerticalAlignment="Stretch">
    <Image Source="/WpfTutorialSamples;component/Images/bullet_green.png" Height="16" DockPanel.Dock="Left" />
    <TextBlock FontStyle="Italic" Foreground="Green">Click to show/hide content...</TextBlock>
</DockPanel>
    </Expander.Header>
    <TextBlock TextWrapping="Wrap" FontSize="18">
    Here we can have text which can be hidden/shown using the built-in functionality of the Expander control.
    </TextBlock>
</Expander>

 

 

아래는 스크롤 가능한 Expander 예시

<Expander Width="200" HorizontalContentAlignment="Stretch">
   <Expander.Header>
     <BulletDecorator>
       <BulletDecorator.Bullet>
         <Image Width="10" Source="images\icon.jpg"/>
       </BulletDecorator.Bullet>
       <TextBlock Margin="20,0,0,0">My Expander</TextBlock>
     </BulletDecorator>
   </Expander.Header>
   <Expander.Content>
     <ScrollViewer Height="50">
       <TextBlock TextWrapping="Wrap">
         Lorem ipsum dolor sit amet, consectetur adipisicing elit, 
         sed do eiusmod tempor incididunt ut labore et dolore magna 
         aliqua. Ut enim ad minim veniam, quis nostrud exercitation 
         ullamco laboris nisi ut aliquip ex ea commodo consequat. 
         Duis aute irure dolor in reprehenderit in voluptate velit 
         esse cillum dolore eu fugiat nulla pariatur. Excepteur sint 
         occaecat cupidatat non proident, sunt in culpa qui officia 
         deserunt mollit anim id est laborum.
       </TextBlock>
     </ScrollViewer>
   </Expander.Content>
 </Expander>

반응형
728x90
반응형

MainWindow.xaml

<Window x:Class="ImageZoomPanning.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:ImageZoomPanning"

        mc:Ignorable="d"

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

    <Grid x:Name="LayoutRoot" Height="300">

        <Grid.RowDefinitions>

            <RowDefinition Height="52.92"/>

            <RowDefinition Height="*"/>

        </Grid.RowDefinitions>

 

        <Border Grid.Row="1" Name="border" Background="Gray" ClipToBounds="True">

            <Image Name="image" Source="iron-man-wallpaper-hd-9.jpg" Opacity="1" RenderTransformOrigin="0.5,0.5" ClipToBounds="True" />

        </Border>

 

    </Grid>

</Window>

MainWindow.xaml.cs

using System.Linq;

using System.Windows;

using System.Windows.Input;

using System.Windows.Media;

 

namespace ImageZoomPanning

{

    /// <summary>

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

    /// </summary>

    public partial class MainWindow : Window

    {

        /// <summary>

        /// 원본 포인트입니다.

        /// </summary>

        private Point origin;

        /// <summary>

        /// 시작 포인트입니다.

        /// </summary>

        private Point start;

 

        /// <summary>

        /// 생성자입니다.

        /// </summary>

        public MainWindow()

        {

            InitializeComponent();

 

            TransformGroup transformGroup = new TransformGroup();

 

            ScaleTransform scaleTransform = new ScaleTransform();

            transformGroup.Children.Add(scaleTransform);

 

            TranslateTransform translateTransform = new TranslateTransform();

            transformGroup.Children.Add(translateTransform);

 

            image.RenderTransform = transformGroup;

 

            image.MouseWheel += image_MouseWheel;

 

            image.MouseLeftButtonDown += image_MouseLeftButtonDown;

            image.MouseLeftButtonUp += image_MouseLeftButtonUp;

            image.MouseMove += image_MouseMove;

        }

 

        /// <summary>

        /// 마우스 휠 움직임에 따라 Zoon In/Out 합니다.

        /// </summary>

        /// <param name="sender"></param>

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

        private void image_MouseWheel(object sender, MouseWheelEventArgs e)

        {

            var transform = (ScaleTransform)((TransformGroup)image.RenderTransform).Children.First(c => c is ScaleTransform);

 

            double zoom = e.Delta > 0 ? .2 : -.2;

            transform.ScaleX += zoom;

            transform.ScaleY += zoom;

        }

 

        /// <summary>

        /// 좌클릭에 따라 패닝을 시작합니다.

        /// </summary>

        /// <param name="sender"></param>

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

        private void image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)

        {

            image.CaptureMouse();

            var translateTransform = (TranslateTransform)((TransformGroup)image.RenderTransform).Children.First(c => c is TranslateTransform);

            start = e.GetPosition(border);

            origin = new Point(translateTransform.X, translateTransform.Y);

        }

 

        /// <summary>

        /// 마우스 우버튼 놓을때 패닝되던 이미지가 멈춥니다

        /// </summary>

        /// <param name="sender"></param>

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

        private void image_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)

        {

            image.ReleaseMouseCapture();

        }

 

        /// <summary>

        /// 마우스 움직임에 따라 이미지가 패닝됩니다.

        /// </summary>

        /// <param name="sender"></param>

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

        private void image_MouseMove(object sender, MouseEventArgs e)

        {

            if (!image.IsMouseCaptured) return;

 

            var translateTransform = (TranslateTransform)((TransformGroup)image.RenderTransform).Children.First(c => c is TranslateTransform);

            Vector v = start - e.GetPosition(border);

            translateTransform.X = origin.X - v.X;

            translateTransform.Y = origin.Y - v.Y;

        }

    }

}

 

 

https://youtu.be/VOmAMaQc2Xg

반응형
728x90
반응형

Property 중 특정 두 값이 조건에 해당 되는 경우 처리를 위해서는 MiltiDataTrigger 를 사용합니다.

 

아래는 StringData1 속성의 값이 "Data1" 이고 StringData2 값이 "Data2" 인경우

Grid 를 숨기는(Visibility=Collapsed) 처리를 합니다.

 

 

    <Grid>

        <Grid.Style>

            <Style TargetType="Grid">

                <Style.Triggers>

                    <MultiDataTrigger>

                        <MultiDataTrigger.Conditions>

                            <Condition Binding="{Binding StringData1}" Value="Data1"/>

                            <Condition Binding="{Binding StringData2}" Value="Data2"/>

                        </MultiDataTrigger.Conditions>

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

                    </MultiDataTrigger>

                </Style.Triggers>

            </Style>

        </Grid.Style>

    </Grid>

 

 

반응형
728x90
반응형

ListView 내부의 Button 클릭시

해당 버튼이 속해있는 Item 을 가져오는 방법입니다.

 

 

 

private void DeleteButton_Click(object sender, RoutedEventArgs e)

{

    var listViewItem = (ListViewItem)listView.ItemContainerGenerator.ContainerFromItem(((Button)sender).DataContext);

   TestItemModel testItemModel = listViewItem.Content as TestItemModel;

}

 

 

반응형
728x90
반응형

하나의 Grid 안에서 두개의 사각형이 있는 경우 이를 서로 영향받을수 있도록 처리하기 위해서 DataDataTrigger 를 이용하면된다.

아래 예시는 하나의 사각형에 마우스가 간 경우 다른 하나의 사각형 컨트롤이 숨겨져있다가 보여지는 처리를 한것이다

<Window x:Class="WpfAppControlTest.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:WpfAppControlTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid HorizontalAlignment="Center">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100"/>
            <ColumnDefinition Width="100"/>
        </Grid.ColumnDefinitions>

        <Rectangle x:Name="B" Grid.Column="0" Fill="Green" Width="100" Height="100"/>

        <Rectangle x:Name="C" Grid.Column="1" Fill="Yellow" Width="100" Height="100">
            <Rectangle.Style>
                <Style TargetType="Rectangle">
                    <Setter Property="Visibility" Value="Collapsed"/>
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding ElementName=B,Path=IsMouseOver}" Value="True">
                            <Setter Property="Visibility" Value="Visible" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </Rectangle.Style>
        </Rectangle>
    </Grid>
</Window>

Grid 의 Trigger 을 통해 처리하는 것을 불가능하며 위 처럼 영향 받고자 하는 컨트롤에 처리를 해주어야한다.

참고 : stackoverflow.com/questions/4208731/create-a-simple-wpf-trigger-on-one-object-that-affects-another

 

반응형
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
반응형
/// <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
반응형

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
반응형

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

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

<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
반응형

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 에서 아래 처럼 해당 항목이 넘어온것을 확인할 수 있다.

 

 

 

반응형

+ Recent posts