2013-07-18 16 views
6

Sprawdź następujący scenariusz (inni mogą mieć zastosowanie również) [można utworzyć projekt po prostu skopiować wkleić kod tutaj po prawej pliku]:Błąd w projektancie Visual Studio WPF?

a - Tworzenie ResourceDictionary z podstawowe rzeczy (Resources.xaml):

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 

    <SolidColorBrush Color="Red" x:Key="Test" /> 

    <Style TargetType="{x:Type GroupBox}" x:Key="Test2" > 
     <Setter Property="Background" Value="Blue" /> 
    </Style> 

    <Style TargetType="{x:Type TextBlock}" > 
     <Setter Property="Foreground" Value="Green" /> 
    </Style> 
</ResourceDictionary> 

b - Tworzenie bazy kontroli użytkownika, gdzie inni będą dziedziczyć zawierający podstawowe zasoby (UserControlBase.cs):

using System.Windows.Controls; 
using System; 
using System.Windows; 

namespace ResourceTest 
{ 
    public class UserControlBase : UserControl 
    { 
     public UserControlBase() 
     { 
      this.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("ResourceTest;component/Resources.xaml", UriKind.RelativeOrAbsolute) }); 
     } 
    } 
} 

c - Tworzenie UserControl dziedziczenie z podstawy (UserControl1.xaml):

<ResourceTest:UserControlBase x:Class="ResourceTest.UserControl1" 

      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:ResourceTest="clr-namespace:ResourceTest" 

      mc:Ignorable="d" 

      d:DesignHeight="300" 
      d:DesignWidth="300" > 
    <Grid> 
     <GroupBox BorderBrush="{StaticResource Test}" Margin="3" Header="Test" Style="{DynamicResource Test2}" > 
      <TextBlock Text="TESTTEST" /> 
     </GroupBox> 

    </Grid> 
</ResourceTest:UserControlBase> 

Wyniki: StaticResources nie zostały rozwiązane (a BorderBrush testowy nie jest załadowany). DynamicResources są rozwiązywane (tło jest niebieskie), ale projektant mówi, że i tak nie może znaleźć zasobu (pierwszy raz działa dobrze, ale kiedy otwierasz/zamykasz projektanta, nie można rozwiązać zasobu). Zasoby niewymienione, takie jak styl TextBlock, działają poprawnie.

Czy to błąd projektanta, czy też robię coś nie tak? Czy dobrze jest zadeklarować zasoby jako dynamiczne w scenariuszu, w którym zasoby nigdy się nie zmienią?

enter image description here

góry dzięki.

+0

Zgadzam się, aby zasoby były dynamiczne, ale nie tak wydajne. Jeśli używasz tego ResourceDictionary tylko tutaj, czy próbowałeś dodać go w 'UserControl.Resources' w przód XAML dla klasy bazowej, aby zobaczyć, czy zachowuje się inaczej? –

+0

@WillEddins: w mojej prawdziwej aplikacji zasoby są ustawione na podstawowym UserControl, więc każda kontrolka ma wymagane zasoby, aby zobaczyć je bezpośrednio na projektorze WPF (w przeciwnym razie style są stosowane tylko w środowisku wykonawczym i nie możemy wykonać właściwego projektu interfejsu użytkownika, chyba że uruchomimy aplikacja dla każdej zmiany: S). –

Odpowiedz

1

Wygląda na to, że projektant ma problemy z rozpoznaniem MergedDictionaries, które są zdefiniowane w kodzie opóźnionym w czasie projektowania.

Jeszcze gorszy przykład można zobaczyć przesuwając ResourceDictionary przed Inicjalizacją.

public UserControl1() 
{ 
    this.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("TempProject;component/Resources.xaml", UriKind.RelativeOrAbsolute) }); 
    InitializeComponent(); 
} 

W tym przypadku DynamicResource nawet nie rozwiązuje w czasie projektowania, wskazując pogląd czas projektowania niekoniecznie jest wywołanie konstruktorów, jak można się spodziewać. Przetestowałem to z Visual Studio 2012, więc to zachowanie nie zmieniło się od 2010 roku.

pod względem oryginalnego kodu testu, należy pamiętać, że StaticResource powiodło się zgodnie z oczekiwaniami w czasie wykonywania (pojawia się czerwona ramka), niezależnie "błędu" rzuconego i braku czerwonej granicy według widoku czasu projektu.

widzę dwie opcje:

  1. Zastosowanie DynamicResource gdzie to konieczne w celu rozwiązania tych w czasie projektowania. Chociaż można użyć StaticResource, skojarzone "błędy" i brak widoku w czasie projektowania będą z pewnością problemem. Other answers seem to indicate there may not be much performance difference między dwoma teraz.

  2. Po prostu stwórz ResourceDictionary w swoim UserControl.Resources i nie dziedzicz z klasy bazowej. Podczas kondensowania trochę kodu przy użyciu klasy bazowej, nie jesteś bardziej wydajny, ponieważ nowa instancja ResourceDictionary będzie tworzona za każdym razem. Ponieważ nie można (AFAIK) rozszerzać z klasy bazowej z front-endem XAML, można potencjalnie argumentować, że na tym poziomie abstrakcji nie ma żadnych odniesień MergedDictionary.

+0

Dzięki Will za czas poświęcony na to. Obecnie używamy podejścia 1, ale jestem trochę zaniepokojony ostrzeżeniem (nawet jeśli nie boli, to nie powinno tam być). Rozwiązanie 2 to nie jest opcja, ponieważ zasoby klasy bazowej są nieco skomplikowane (możesz zmienić styl aplikacji w czasie wykonywania), więc w grę wchodzi kilka słowników zasobów. Aby utrudnić działanie, chcemy widzieć kontrole w czasie takim jak w środowisku wykonawczym, więc dodajemy zasoby tylko w wyznaczonym czasie (w przeciwnym razie pochodzą one z aplikacji). Właśnie dlatego stworzyliśmy bazę UserControl ... –

+0

Czy uważasz, że powinniśmy zgłosić błąd do Ms? –

+0

@SoMoS Chciałbym usłyszeć od kogoś, kto jest bardziej zaznajomiony z działaniem projektanta pod względem wywołań konstruktorów i tym podobnych. Jednakże pod względem zmiany stylu w środowisku wykonawczym, zwykle oczekiwałbym zmiany 'ResourceDictionary' na poziomie' Application.Resources'. Nawet jeśli zdefiniowałeś 'ResourceDictionary' w przykładzie jako statyczny (tak, że jest on współdzielony po dodaniu), nadal musiałbyś zmienić MergedDictionary na podstawie poszczególnych instancji, czyż nie? Jestem pewien, że twoja implementacja jest inna, ale wydaje się to skomplikowanym sposobem. –

Powiązane problemy