런타임에 XAML을 로드하시겠습니까?
첫 번째 몇 가지 배경:저는 애플리케이션을 작성하고 있으며 MVVM 규약을 따르려고 노력하고 있습니다.제가 하고 싶은 한 가지는 애플리케이션에 다른 "스킨"을 부여하는 것입니다.동일한 애플리케이션이지만 한 클라이언트에 대해 하나의 "스킨"을 표시하고 다른 클라이언트에 대해 다른 "스킨"을 표시합니다.
그래서 제 질문은 다음과 같습니다.
실행 시 xaml 파일을 로드하여 내 앱에 "할당"할 수 있습니까?
xaml 파일이 다른 폴더에 있는 외부 파일일 수 있습니까?
응용 프로그램이 다른 xaml 파일로 쉽게 전환할 수 있습니까, 아니면 시작할 때만 전환할 수 있습니까?
그렇다면 어디서부터 이에 대한 정보를 찾아야 할까요?어떤 WPF 방법이 존재할 경우 이 기능을 처리합니까?
감사합니다!
편집: 제가 하고 싶은 "가죽 벗기기" 유형은 단순히 제 컨트롤의 모양을 바꾸는 것 이상입니다.그 아이디어는 완전히 다른 UI를 가지고 있습니다.버튼도 다르고 레이아웃도 다릅니다.마치 한 버전의 앱이 전문가들을 위해 완전히 기능하고 다른 버전은 초보자들을 위해 단순화되는 것과 같습니다.
Jakob Christensen이 언급했듯이, 당신은 당신이 사용하기를 원하는 모든 XAML을 로드할 수 있습니다.XamlReader.Load스타일에만 해당되는 것은 아니지만,UIElement마찬가지로다음과 같이 XAML을 로드하면 됩니다.
UIElement rootElement;
FileStream s = new FileStream(fileName, FileMode.Open);
rootElement = (UIElement)XamlReader.Load(s);
s.Close();
그런 다음 적합한 요소의 내용으로 설정할 수 있습니다. 예:
<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>
추가할 수 있습니다.rootElement에서grid포함:
layoutGrid.Children.Add(rootElement);
layoutGrid.SetColumn(rootElement, COLUMN);
layoutGrid.SetRow(rootElement, ROW);
또한 자연스럽게 내부 요소에 대한 이벤트를 연결해야 합니다.rootElement수동으로 암호화합니다.예를 들어, 다음과 같이 가정합니다.rootElement포함Canvas많은Paths, 할당할 수 있습니다.Paths'의MouseLeftButtonDown다음과 같은 이벤트:
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;
}
}
저는 XAML 파일을 즉시 전환하려고 시도하지 않았기 때문에, 그것이 정말로 효과가 있을지 어떨지 말할 수 없습니다.
저는 이것이 XamlReader로 꽤 간단하다고 생각합니다. 이것을 시도해 보세요. 제가 직접 시도한 것은 아니지만, 효과가 있을 것이라고 생각합니다.
https://learn.microsoft.com/en-us/archive/blogs/ashish/dynamically-loading-xaml
xaml을 로드하는 간단한 마크업 확장을 만들었습니다.
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");
}
}
용도:
MyFirstView.xaml 파일을 찾아서 로드합니다.
<ContentControl Content="{wpf:DynamicXamlLoader XamlFileName=MyFirstView.xaml}" />
이렇게 하면 전체 UserControl이 채워집니다(MySecondView.xaml 파일을 찾아서 로드).
<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}" />
XamlReader를 사용하여 원하는 모든 XAML을 로드할 수 있습니다.싣습니다.
응용프로그램에서 모든 컨트롤의 스타일을 지정하고 응용프로그램 리소스 사전에서 해당 스타일을 정의하면 XamlReader를 사용하여 XAML에 정의된 새 스타일을 다른 곳에 로드할 수 있습니다.리소스 사전의 일부를 로드하고 로드된 XAML로 교체합니다. 이에 따라 컨트롤의 모양이 변경됩니다.
런타임에 XAML을 로드했습니다. 여기 짧은 예가 있습니다.
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>";
이미 다른 답변에서 언급했듯이, 당신은 을 사용할 수 있습니다.
좀 더 간단한 예를 찾는 경우 XAML이 포함된 문자열 변수에서 컨트롤을 얼마나 쉽게 만들 수 있는지 보여주는 예를 다음에 제시된 예는 다음과 같습니다.
public T LoadXaml<T>(string xaml)
{
using (var stringReader = new System.IO.StringReader(xaml))
using (var xmlReader = System.Xml.XmlReader.Create(stringReader))
return (T)System.Windows.Markup.XamlReader.Load(xmlReader);
}
사용법에 따라 다음과 같습니다.
var xaml = "<TextBox xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation\'>" +
"Lorm ipsum dolor sit amet." +
"</TextBox>";
var textBox = LoadXaml<System.Windows.Controls.TextBox>(xaml);
언급URL : https://stackoverflow.com/questions/910814/loading-xaml-at-runtime
'source' 카테고리의 다른 글
| 'app/hero.ts' 파일은 콘솔의 모듈 오류가 아닙니다. angular2의 디렉토리 구조에서 인터페이스 파일을 저장할 위치는 어디입니까? (0) | 2023.04.27 |
|---|---|
| C#의 배열과 같은 목록을 초기화할 수 있는 이유는 무엇입니까? (0) | 2023.04.27 |
| TemplateRef!(NgIf ->TemplateRef) 제공자가 없습니다. (0) | 2023.04.27 |
| Install-Module : 'Install-Module' 용어가 cmdlet의 이름으로 인식되지 않습니다. (0) | 2023.04.27 |
| 길을 잃었어요.ASP에 무슨 일이 있었습니까?NET MVC 5? (0) | 2023.04.27 |