2009-05-26 54 views
42

İlk önce arka plan: Bir uygulama üzerinde çalışıyorum ve bunu yazarken MVVM kurallarına uymaya çalışıyorum. Yapmak istediğim bir şey, uygulamayı uygulamaya farklı "derileri" verebilmek. Aynı uygulama, ancak bir müşteri için bir "cilt" ve başka bir için farklı bir "cilt" göster.Çalışma zamanında XAML yükleniyor?

Sorularım şunlardır:
1. Çalışma zamanında bir xaml dosyası yüklemek ve uygulamayı "atamak" mümkün müdür?
2. xaml dosyası farklı bir klasörde bulunan harici bir dosya olabilir mi?
3. Uygulama başka bir xaml dosyasına kolayca veya yalnızca başlangıç ​​saatine geçebilir mi?

Bu konu hakkında bilgi almaya nereden başlamalıyım? Varsa, hangi WPF yöntemleri bu işlevselliği kullanır?

Teşekkürler!

Düzenleme: yapmak istediğim "kaplama" türü, yalnızca denetimlerimin görünümünü değiştirmekten daha fazlasıdır. Fikir tamamen farklı bir kullanıcı arayüzü yaşıyor. Farklı düğmeler, farklı düzenler. Uygulamanın bir sürümünün uzmanlar için tam olarak nasıl kullanılacağına ve başka bir sürümün yeni başlayanlar için nasıl basitleştirileceğine benzer.

cevap

4

XamlReader.Load'u kullanarak istediğiniz herhangi bir XAML'yi yükleyebilirsiniz.

Tüm denetimlerinizi uygulamanızda şekillendirirseniz ve uygulama kaynaklarınızdaki bu stilleri tanımlarsanız, XamlReader.Load kullanarak başka bir yerde XAML'de tanımlanan yeni stilleri yükleyebilir ve kaynak sözlüğünüzün bölümlerini yüklenen XAML ile değiştirebilirsiniz. Kontrolleriniz buna göre görünümü değiştirecektir.

33

Jakob Christensen belirtildiği gibi, size XamlReader.Load kullanarak istediğiniz herhangi XAML yükleyebilir. Bu yalnızca stiller için geçerli değildir, ancak UIElement s. Eğer örneğin, uygun elemanın içeriğinin yanı ayarlayabilirsiniz Sonra

UIElement rootElement; 
FileStream s = new FileStream(fileName, FileMode.Open); 
rootElement = (UIElement)XamlReader.Load(s); 
s.Close(); 

: gibi sadece XAML yüklemek

<Window x:Class="MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Foo Bar"> 
    <Grid x:Name="layoutGrid"> 
     <!-- any static elements you might have --> 
    </Grid> 
</Window> 

için sizinle grid yılında rootElement ekleyebilirsiniz: Sen doğal olarak elle de kod arkasında rootElement içindeki elementler için herhangi olayları bağlamak gerekecek

layoutGrid.Children.Add(rootElement); 
layoutGrid.SetColumn(rootElement, COLUMN); 
layoutGrid.SetRow(rootElement, ROW); 

. Bir örnek olarak, varsayarak rootElement böyle Path s'MouseLeftButtonDown olay atayabilir Path s bir grup ile bir Canvas içerir:

Canvas canvas = (Canvas)LogicalTreeHelper.FindLogicalNode(rootElement, "canvas1"); 
foreach (UIElement ui in LogicalTreeHelper.GetChildren(canvas)) { 
    System.Windows.Shapes.Path path = ui as System.Windows.Shapes.Path; 
    if (path != null) { 
     path.MouseLeftButtonDown += this.LeftButtonDown; 
    } 
} 

ben anında XAML dosyaları anahtarlama denemedim, o yüzden Gerçekten işe yarayıp yaramadığını söyleyemem.

+0

Merhaba TomiJ! Bu, aradığım şeyle ilgili gibi görünüyor. Eksik olan tek şey, çözümün bir parçası olan .xaml dosyalarının nasıl işleneceğidir. Nasıl gidip onları yüklerim? – djcouchycouch

+0

Üzerinde çalıştığım uygulamada, XAML dosyalarını çözümde tutuyorum ve Build Action'unu "none" ("Yok") olarak ayarlıyorum ve Visual Studio'nun dosyaları daha yeni çıktılarsa çıktı dizinine kopyalamasını sağlıyorum. Yukarıdaki ilk kod pasajı daha sonra bunları yüklemek için kullanılacaktır. –

+0

Aradıgım, burada bir xaml yükleme kaynağı olarak http://msdn.microsoft.com/en-us/library/aa970494.aspx – djcouchycouch

0

http://www.codeproject.com/Articles/19782/Creating-a-Skinned-User-Interface-in-WPF - Josh Smith, WPF'de nasıl ciltleneceğine dair harika bir makale yazdı.

public class DynamicXamlLoader : MarkupExtension 
{ 
    public DynamicXamlLoader() { } 

    public DynamicXamlLoader(string xamlFileName) 
    { 
     XamlFileName = xamlFileName; 
    } 

    public string XamlFileName { get; set; } 

    public override object ProvideValue(IServiceProvider serviceProvider) 
    { 
     var provideValue = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget; 
     if (provideValue == null || provideValue.TargetObject == null) return null; 

     // get target 
     var targetObject = provideValue.TargetObject as UIElement; 
     if (targetObject == null) return null; 

     // get xaml file 
     var xamlFile = new DirectoryInfo(Directory.GetCurrentDirectory()) 
      .GetFiles(XamlFileName ?? GenerateXamlName(targetObject), SearchOption.AllDirectories) 
      .FirstOrDefault(); 

     if (xamlFile == null) return null; 

     // load xaml 
     using (var reader = new StreamReader(xamlFile.FullName)) 
      return XamlReader.Load(reader.BaseStream) as UIElement; 
    } 

    private static string GenerateXamlName(UIElement targetObject) 
    { 
     return string.Concat(targetObject.GetType().Name, ".xaml"); 
    } 
} 

Kullanımı:

Bu bulup

4

Burada, zamanında XAML yükleme yapmış ben xaml yükler basit biçimlendirme uzantısı, yapılan

Grid grd = new Grid(); 
var grdEncoding = new ASCIIEncoding(); 
var grdBytes = grdEncoding.GetBytes(myXAML); 
grd = (Grid)XamlReader.Load(new MemoryStream(grdBytes)); 
Grid.SetColumn(grd, 0); 
Grid.SetRow(grd, 0); 
parentGrid.Children.Add(grd); 

private String myXAML = @" <Grid xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' Margin='30 10 30 65' VerticalAlignment='Bottom'>" + 
        "<Label Content='Date: 1-Feb-2013' FontFamily='Arial' FontSize='12' Foreground='#666666' HorizontalAlignment='Left'/>" + 
        "<Label Content='4' FontFamily='Arial' FontSize='12' Foreground='#666666' HorizontalAlignment='Center'/>" + 
        "<Label Content='Hello World' FontFamily='Arial' FontSize='12' Foreground='#666666' HorizontalAlignment='Right'/>" + 
       "</Grid>"; 
4

kısa örnektir yükleme MyFirstView.xaml dosya

.210

Ve bu dolgu bütün UserControl (bulmak ve yük MySecondView.xaml dosyası)

<UserControl x:Class="MySecondView" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Content="{wpf:DynamicXamlLoader}" /> 
İlgili konular