program tip

app.xaml에서 기본 WPF 창 스타일을 설정하는 방법은 무엇입니까?

radiobox 2020. 11. 25. 07:51
반응형

app.xaml에서 기본 WPF 창 스타일을 설정하는 방법은 무엇입니까?


내 app.xaml에서 내 WPF Windows 응용 프로그램의 모든 창에 대해 기본 스타일을 설정하려고합니다. 지금까지 app.xaml에 다음이 있습니다.

<Application.Resources>
    <ResourceDictionary>
        <Style x:Key="WindowStyle" TargetType="{x:Type Window}">
            <Setter Property="Background" Value="Blue" />
        </Style>
    </ResourceDictionary>
</Application.Resources>

다음을 통해 창에이 스타일을 사용하도록 구체적으로 지시하여 앱을 실행할 때 (VS 디자이너는 아님)이 스타일로 창을 표시 할 수 있습니다.

Style="{DynamicResource WindowStyle}

이것은 작동하지만 이상적이지 않습니다. 그래서 어떻게 :

  1. 모든 창에서 자동으로 스타일을 사용합니까 (모든 창에서 지정할 필요가 없음)?
  2. VS 디자이너가 스타일을 보여 주 었나요?

감사!


Ray의 말에 추가하려면 :

스타일의 경우 키 / ID를 제공하거나 TargetType을 지정해야합니다.

FrameworkElement에 명시 적으로 지정된 Style이 없으면 항상 자체 형식을 키로 사용하여 Style 리소스를 찾습니다.
프로그래밍 WPF (Sells, Griffith)

TargetType을 제공하면 해당 유형의 모든 인스턴스에 스타일이 적용됩니다. 그러나 파생 된 유형은 그렇지 않습니다. <Style TargetType="{x:Type Window}">모든 사용자 지정 파생 / 창에서 작동하지 않습니다. <Style TargetType="{x:Type local:MyWindow}">MyWindow에만 적용됩니다. 그래서 옵션은

  • 스타일 을 적용하려는 모든 창의 스타일 속성으로 지정한 키 스타일을 사용합니다 . 디자이너는 스타일이 지정된 창을 표시합니다.

.

    <Application.Resources>
        <Style x:Key="MyWindowStyle">
            <Setter Property="Control.Background" Value="PaleGreen"/>
            <Setter Property="Window.Title" Value="Styled Window"/>
        </Style>
    </Application.Resources> ...
    <Window x:Class="MyNS.MyWindow" Style="{StaticResource MyWindowStyleKey}">  ...
  • 또는 Ctor / Initialization / Load 단계에서 Style 속성을 한 번 설정 하는 사용자 지정 BaseWindow 클래스 ( 고유 한 특성이 있음)에서 파생 할 수 있습니다 . 그러면 모든 파생물에 자동으로 스타일이 적용됩니다. 하지만 디자이너는 스타일을 인식하지 못할 것입니다 . 스타일이 적용되는지 확인하려면 앱을 실행해야합니다. 디자이너가 InitializeComponent (자동 / 디자이너 생성 코드)를 실행하기 만하면 XAML이 적용되지만 사용자 지정이 아닌 것 같습니다. 코드 숨김.

그래서 명시 적으로 지정된 스타일이 가장 적은 작업이라고 말하고 싶습니다. 어쨌든 중앙에서 스타일의 측면을 변경할 수 있습니다.


몇 년이 지났지 만 질문이 여전히 여기에 있기 때문에 ...

  1. 프로젝트에서 리소스 사전 만들기 (프로젝트를 마우스 오른쪽 버튼으로 클릭 ...)

    프로젝트 아래에 "Assets"라는 새 폴더를 만들고 여기에 "resourceDict.XAML을 넣습니다.

  2. resourceDict.XAML에 코드를 추가합니다.

    <Style x:Key="WindowStyle" Target Type="Window" >
         <Setter Property="Background" Value="Blue" />
    </Style>
    
  3. 프로젝트 XAML 파일에서 창 아래에 다음을 추가합니다.

    <Window.Resources>
        <ResourceDictionary>
            <!-- Believe it or not the next line fixes a bug MS acknowledges -->
            <Style TargetType="{x:Type Rectangle}" />
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/Assets/resourceDict.XAML" />
            </ResourceDictionary.MergedDictionaries>
        <ResourceDictionary>
    </Window.Resources>
    

    다음 웹 사이트를 참조 하십시오. 병합 된 사전이 포함 된 리소스 사전을 참조하는 데 문제가 있습니다. "버그가 있습니다. 모든 기본 스타일이 병합 된 사전에 3 단계 깊이 (또는 그 이상) 중첩 된 경우 상위 사전에 플래그가 지정되지 않아 검색이 건너 뜁니다. 해결 방법은 기본 스타일을 루트 사전에있는 어떤 것, 무엇이든 배치하는 것입니다. " 그리고 안정적으로 문제를 해결하는 것 같습니다. 그림을 이동...

  4. 마지막으로, Window 아래, 아마도 Title 뒤, 마지막 Window '>'앞 :

    Style="{DynamicResource windowStyle}"
    
  5. 스타일을 적용 할 모든 프로젝트에 3 단계와 4 단계의 코드를 추가해야합니다.

  6. 단색이 아닌 그라데이션 배경을 사용하려면 resourceDict.XAML에 다음 코드를 추가하세요.

    <LinearGradientBrush x:Key="windowGradientBackground" StartPoint="0,0"
            EndPoint="0,1" >
    <GradientStop Color= "AliceBlue" Offset="0" />
    <GradientStop Color= "Blue" Offset=".75" />
    </LinearGradientBrush>
    
  7. 그리고 배경색을 읽을 수 있도록 스타일 설정기를 수정하십시오.

    <Setter Property="Background" Value="{DynamicResource
            windowGradientBackground}" />
    

위에서 설명한대로 각 project.XAML 파일에서 3 단계와 4 단계를 반복해야하지만 솔루션 전반에 걸쳐 균일 한 Windows가 제공됩니다! 그리고 동일한 프로세스가 버튼 등 균일 한 모양을 원하는 모든 컨트롤에 적용될 수 있습니다.

이 늦게 오는 사람에게 도움이되기를 바랍니다. 원본 포스터가이 모든 것을 몇 년 전에 알아 냈을 것이라고 확신합니다.


DynamicResource를 지정했기 때문에 디자이너가 작동하지 않습니다. 이것을 StaticResource로 변경하면 모두 잘 될 것입니다.

모든 창에 적용하려면 스타일에서 x : Key를 제거해야합니다. TargetType을 설정하면 x : Key가 TargetType에있는 것으로 암시 적으로 설정됩니다. 그러나 내 테스트에서 이것은 작동하지 않으므로 조사하고 있습니다.

TargetType을 x : Type TextBlock으로 설정하면 디자이너가 완벽하게 작동하며 다른 동작을 보여주는 창인 것 같습니다.


이 코드를 App.xaml.cs 파일에 추가 할 수 있습니다.

        FrameworkElement.StyleProperty.OverrideMetadata(typeof(Window), new FrameworkPropertyMetadata
        {
            DefaultValue = Application.Current.FindResource(typeof(Window))
        });

그런 다음 Window유형에 적용된 스타일 은 다음에서 파생 된 모든 유형에도 적용됩니다.Window


나는 며칠 동안 이것을 조사하고 내 사용자 정의 Window 클래스의 생성자를 통해 작동하도록 만들었습니다.

public class KWindow : Window
{
        public KWindow()
        {
            this.SetResourceReference(StyleProperty, typeof(KWindow));
        }

        static KWindow()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(KWindow), new FrameworkPropertyMetadata(typeof(KWindow)));

        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            // gets called finally
        }
}

누군가에게 도움이되기를 바랍니다.


이 문제에 대한 해결책으로 어려움을 겪는 사람들을 위해 : 사용자 정의 스타일을 모든 Window 파생 유형에 자동으로 적용하려면 어떻게해야합니까? 아래는 내가 생각해 낸 해결책입니다.

NOTE: I really didn't want to derive from the Window type or have to insert XAML on each window to force a style update etc. for reasons specific to my project (consumers of my product us my generic reusable style library and create their own layout/windows etc.) so I was really motivated to figure a solution out that worked that I was willing to live with any side effects

Need to iterate through all the instantiated windows and simply force them to use the new custom style you have defined for the Window type. This works great for windows that are already up but when a window or child window is instantiated it won't know to use the new/custom type that has been declared for its base type; the vanilla Window type. So the best I could come up with was to use the LostKeyBoardFocus on the MainWindow for when it loses Focus to a ChildWindow (IOW When a child window has been created) and then invoke this FixupWindowDerivedTypes().

If someone has a better solution for "detecting" when any kind of window derived type is instantiated and thus call the FixupWindowDerivedTypes() that would be great. There may be something useful with handling the WM_WINDOWPOSCHANGING in this area as well.

So this solution is not elegant per say but gets the job done without me having to touch any code or XAML related to my windows.

   public static void FixupWindowDerivedTypes()
    {
        foreach (Window window in Application.Current.Windows)
        {
           //May look strange but kindly inform each of your window derived types to actually use the default style for the window type

                    window.SetResourceReference(FrameworkElement.StyleProperty, DefaultStyleKeyRetriever.GetDefaultStyleKey(window));
                }
            }
        }
    }


//Great little post here from Jafa to retrieve a protected property like DefaultStyleKey without using reflection.
http://themechanicalbride.blogspot.com/2008/11/protected-dependency-properties-are-not.html

//Helper class to retrieve a protected property so we can set it
internal class DefaultStyleKeyRetriever : Control
{
    /// <summary>
    /// This method retrieves the default style key of a control.
    /// </summary>
    /// <param name="control">The control to retrieve the default style key 
    /// from.</param>
    /// <returns>The default style key of the control.</returns>
    public static object GetDefaultStyleKey(Control control)
    {
        return control.GetValue(Control.DefaultStyleKeyProperty);
    }
}

Considering Gishu's answer I figured out one more workaround. But it could be little bit weird. If you use MVVM pattern you could remove code-behind of your window and x:Class markup in XAML file. So you will get an instance of window or your custom window but not a some instance of 'MainWindow' class that is derived from 'Window' class and marked as partial. I'm making VS-like window so I had to inherit window class and extend it functionality. In that case it will be possible to make new window class as partial that would allow us to make code-behind without inheritance.


  1. you will save all the styles in one xaml file(example design.xaml)

  2. and then call that (design.xaml) xaml file in all the pages like this way

Like:

<ResourceDictionary.MergedDictionaries>
                <ResourceDictionary  Source="Design.xaml"/>                
</ResourceDictionary.MergedDictionaries>

참고URL : https://stackoverflow.com/questions/431940/how-to-set-default-wpf-window-style-in-app-xaml

반응형