资源引用
WPF中的资源包含很多,如图片、字体、声音,以及样式、模板等很多,在使用的时候常常出现很多问题。
绑定图片路径
需求:程序发布后,可以更换图片
一定要使用绝对路径,相对路径不行
前端
<UserControl xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core" xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors" x:Class="OESTS.Modules.Login.Views.LoginView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:Control="clr-namespace:OESTS.Control;assembly=OESTS.Control"
xmlns:core="clr-namespace:OESTS.Core.Events;assembly=OESTS.Core"
prism:ViewModelLocator.AutoWireViewModel="True" Margin="0"
Width="1280" Height="720">
<UserControl.Background>
<ImageBrush ImageSource="{Binding BackgroundImagesource}" />
</UserControl.Background>
后端
public class LoginViewModel : RegionViewModelBase
{
private string _backgroundImagesource;
public string BackgroundImagesource
{
get { return _backgroundImagesource; }
set { SetProperty(ref _backgroundImagesource, value); }
}
public LoginViewModel()
{
//注意,一定要使用绝对路径,相对路径不行
//加载背景图,在exe文件的 Assets/bg.png
BackgroundImagesource = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,"Assets/bg.png");
}
}
资源路径
在WPF开发中,对资源的管理非常重要,当我们存在多个项目时,最好是把所有的资源都放在一个基础项目中进行管理,方便维护。
正确的做法使用
pack://application:,,,/程序集名称;component/资源路径名
图片资源路径
存在两个项目
- 基础项目名称:Demo.Infrastructure
- 主项目 Demo
所有的资源在 Demo.Infrastructure
中定义
- 正确的使用
<UserControl.Background>
<!---->
<ImageBrush ImageSource="pack://application:,,,/
Demo.Infrastructure;component/images/login_bg.png"/>
</UserControl.Background>
- 错误的使用(不加 pack://application:,,,)此时为相对路径,在编辑模式下可以看到图片,但是运行后不显示
<UserControl.Background>
<!---->
<ImageBrush ImageSource="/
Demo.Infrastructure;component/images/login_bg.png"/>
</UserControl.Background>
- 错误的使用(不加 pack://application:,,, 和命名空间)
<UserControl.Background>
<!---->
<ImageBrush ImageSource="images/login_bg.png"/>
</UserControl.Background>
字体资源路径
可以下载阿里巴巴的字体文件,下载后将ttf文件拷贝到项目中
<TextBlock Text="" FontFamily="{StaticResource iconfont}" FontSize="14" Foreground="Red" VerticalAlignment="Center" />
<TextBlock Text="" FontFamily="/OESTS.Modules.Login;component/fonts/#iconfont" FontSize="14" Foreground="Red" VerticalAlignment="Center" />
<TextBlock Text="" FontFamily="/fonts/#iconfont" FontSize="14" Foreground="Red" VerticalAlignment="Center"/>
LoadComponent使用的路径
加载组件函数,可以加载一个xaml文件,这里页存在一个资源路径的问题,此方法仅能使用相对路径,不能使用绝对路径
案例:需求加载一个流文档控件的文件资源,
文件名为flowdoc.xaml,如下
<FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
TextOptions.TextFormattingMode="Display" >
<Paragraph>
<Run Text="加载测试" ></Run>
</Paragraph>
</FlowDocument>
- 当只有一个项目时,若文件存在项目的resources文件中,加载方式如下
FlowDocument doc = (FlowDocument)Application.LoadComponent(new Uri("/resources/flowdoc.xaml", UriKind.Relative));
- 当存在多个项目,如使用了Prism框架,在一个模块项目中加载时(模块项目的程序集为:DemoModule)
//正确的做法
FlowDocument doc = (FlowDocument)Application.LoadComponent(
new Uri("/DemoModule;component/resources/flowdoc.xaml",
UriKind.Relative));
//错误的做法,不能加pack://application:,,,,加了后为绝对路径
FlowDocument doc = (FlowDocument)Application.LoadComponent(
new Uri("pack://application:,,,DemoModule;component/resources/flowdoc.xaml",
UriKind.Relative));
资源的引用方式
- 本地添加模板目录:分别创建模板对象。
- App.xaml中添加模板目录,创建全局模板对象,导致大家的数据相同。
- 对于样式、转换器、模板选择器等,在App.xaml添加目录比较合适。
- 对于模板的使用,在本地添加模板目录不会出现问题。
- 如果两者都添加,本地添加的起作用。
场景描述: 当前有两个页面(AView,BView)的布局相同,数据不同,定义了一个通用模板为 ContentTemplate
, 定义了通用模板,key 为 contentView
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:ScreenControlE" >
<Grid x:Key="contentView">
<TextBlock Text="{Binding Path=Content}" FontSize="14" Foreground="Red" VerticalAlignment="Center" />
</Grid>
</ResourceDictionary>
A、B页面在本地添加模板目录
- A、B页面的前端(这里使用了Prsim框架),在本地添加了资源目录,并引用
contentView
,此时两个页面显示正常,分别显示自己的内容
<UserControl x:Class=" ScreenControlE.Views.NCCView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True">
<UserControl.Resources>
<ResourceDictionary Source="/Themes/ContentTemplate.xaml"/>
</UserControl.Resources>
<Grid>
<ContentControl x:Name="ncc_contentCrl" Content="{StaticResource contentView }"/>
</Grid>
</UserControl>
在App.xaml中添加模板的目录
- App.xaml
<prism:PrismApplication x:Class="ScreenControlE.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ScreenControlE"
xmlns:prism="http://prismlibrary.com/" >
<Application.Resources>
<ResourceDictionary Source="/Themes/ContentTemplate.xaml"/>
</Application.Resources>
</prism:PrismApplication>
- A、B页面的前端(这里使用了Prsim框架),直接引用
contentView
<UserControl x:Class=" ScreenControlE.Views.NCCView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True">
<Grid>
<ContentControl x:Name="ncc_contentCrl" Content="{StaticResource contentView }"/>
</Grid>
</UserControl>
-
两个页面显示了相同的内容,在App.xaml中添加的相当于创建了一个全局变量的对象
-
ViewModel(A为例)
public class AViewModel : ViewModelBase
{
public string Content { get; set; } = "A模板"
}