我有两个库和一个应用程序集程序项目布局,我想知道如何通过其中一个我在另一个库中定义的库中的键来引用样式.
我的解决方案布局
我已经看到一些示例解释如何使用简单的单个控件库和应用程序组件来执行此操作,但在我的情况下,我有两个程序集和一个应用程序.所以换句话说在我的情况下,我的第二个控件库中没有App.xaml,我可以使用MergeDictionaries概念.我很确定我是否可以直接在每个控件XAML文件中放置一个MergedDictionaries引用来合并WpfControls.dll程序集中定义的所有Generic.xaml但我的猜测是这会导致样式被冗余地合并到各个地方在我的SpecializedControls程序集中,这似乎不是最好的解决方案.更糟糕的是,这些词典也可能合并到Application.exe中,这会在运行时开始膨胀我的应用程序吗?
任何人都可以用最少的编程和资源开销来澄清分享这些样式的推荐或最佳方法.
更新:经过一些测试后,即使在同一个程序集中,我也无法通过它的密钥引用Generic.xaml中定义的任何资源.关于我如何理解资源键的工作方式可能存在一些完全错误,所以我需要进行更多的研究以及调查ComponentResourceKey.如果有人有任何提示或建议,请帮助.
我有一个带有以下TextBlock的WPF ResourceDictionary:
<TextBlock Visibility="{Binding Converter={StaticResource MyBoolProp ResourceKey=BoolToVis}}">
</TextBlock>
Run Code Online (Sandbox Code Playgroud)
ResourceDictionary包含在MergedDictionaries下的App.xaml中:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="MyResourceDictionary.xaml"/>
Run Code Online (Sandbox Code Playgroud)
在App.xaml中,我定义了BoolToVis转换器(再次,在下Application.Resources)
<BooleanToVisibilityConverter x:Key="BoolToVis" />
Run Code Online (Sandbox Code Playgroud)
当我启动我的应用程序时 - 我得到以下XamlParseException:
"在'System.Windows.Markup.StaticResourceHolder'上提供价值引发了异常."
InnerException是:
"找不到名为'BoolToVis'的资源.资源名称区分大小写."
我可以直接用App.xaml引用这个转换器(事实上,特定的XAML声明是相同的),并且在其他UserControl中没有问题.
这个特殊的代码在.NET 4.0 RC(和Beta2)下运行良好.仅当我升级到.NET 4.0 RTM时才会发生此错误.
我可以通过BooleanToVisibilityConverter在MyResourceDictionary.xaml中声明另一个并且像这样引用它来解决它:
<TextBlock Visibility="{Binding Converter={StaticResource MyBoolProp ResourceKey=BoolToVis2}}">
</TextBlock>
Run Code Online (Sandbox Code Playgroud)
有什么理由我需要这样做吗?
我有一个ComboBox,我需要在我的应用程序的多个地方使用,所以我设置大部分的属性ComboBox中ResourceDictionary和使用,作为一个风格在以往任何时候我需要它.
风格ComboBox是:
<Style TargetType="{x:Type ComboBox}" x:Key="ComboBoxBranch">
<Setter Property="ItemsSource" Value="{Binding Branches}"></Setter>
<Setter Property="DisplayMemberPath" Value="BranchName"></Setter>
<Setter Property="SelectedItem" Value="{Binding SelectedBranch}"></Setter>
</Style>
Run Code Online (Sandbox Code Playgroud)
我在我的XAML中使用它是这样的:
<ComboBox Style="{StaticResource ComboBoxBranch}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding SelectCustomerCommand}" CommandParameter="{Binding SelectedBranch}" ></i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
Run Code Online (Sandbox Code Playgroud)
我想移动交互触发器代码ResourceDictionary,所以我不需要在我的所有xamls中编写它.有可能吗?
我在XAML中有一个已定义的路径:
<UserControl.Resources>
<ResourceDictionary>
<Path x:Key="N44" Width="20" Height="80" Stretch="Fill" Fill="#FF000000" Data="M 20,25.2941L 20,29.4118L 15.9091,29.4118L 15.9091,40L 12.2727,40L 12.2727,29.4118L 2.54313e-006,29.4118L 2.54313e-006,25.6985L 13.4872,7.62939e-006L 15.9091,7.62939e-006L 15.9091,25.2941L 20,25.2941 Z M 12.2727,25.2941L 12.2727,5.28493L 2.09517,25.2941L 12.2727,25.2941 Z M 20,65.2941L 20,69.4118L 15.9091,69.4118L 15.9091,80L 12.2727,80L 12.2727,69.4118L -5.08626e-006,69.4118L -5.08626e-006,65.6985L 13.4872,40L 15.9091,40L 15.9091,65.2941L 20,65.2941 Z M 12.2727,65.2941L 12.2727,45.2849L 2.09517,65.2941L 12.2727,65.2941 Z "/>
</ResourceDictionary>
</UserControl.Resources>
Run Code Online (Sandbox Code Playgroud)
我想将它添加到WPF Gird并像这样工作一次:
System.Windows.Shapes.Path aPath = new System.Windows.Shapes.Path();
aPath = (System.Windows.Shapes.Path)this.Resources["N44"];
LayoutRoot.Children.Add(aPath);
Run Code Online (Sandbox Code Playgroud)
但是,如果我在按钮单击事件上添加此代码,然后单击该按钮两次,则会引发错误
"指定的Visual已经是另一个Visual的子项或CompositionTarget的根."
然后我尝试创建资源的两个实例,但我继续收到相同的错误.以下是我用于此测试的代码:
private void cmbTest_Click(object sender, System.Windows.RoutedEventArgs e)
{
System.Windows.Shapes.Path aPath = new System.Windows.Shapes.Path();
aPath = …Run Code Online (Sandbox Code Playgroud) 我有一个简单的模板,用于以这种方式构造的组合框:
<ComboBox DockPanel.Dock="Left" MinWidth="100" MaxHeight="24"
ItemsSource="{Binding Actions}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" Width="100" />
<Image Source="{Binding Converter={StaticResource TypeConverter}}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Run Code Online (Sandbox Code Playgroud)
所以,如果我使用这个代码,一切正常:
<TextBlock Text="{Binding Name}" Width="100" />
<!--<Image Source="{Binding Converter={StaticResource TypeConverter}}" /> -->
<Image Source="{StaticResource SecurityImage}" />
Run Code Online (Sandbox Code Playgroud)
但是,如果我使用转换器,它就不再起作用了.这是转换器,但我不知道如何从那里引用静态资源...
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var type = (Action)value;
var img = new BitmapImage();
switch (type.ActionType)
{
case ActionType.Security:
img.UriSource = new Uri("StructureImage", UriKind.Relative);
break;
case ActionType.Structural:
img.UriSource = new Uri("SecurityImage", UriKind.Relative); …Run Code Online (Sandbox Code Playgroud) 我的情况是这样的.我在WPF解决方案下有多个项目,构成我正在开发的多层应用程序.由于单独的项目有时需要访问相同的图像或xaml资源,我希望将"公共"资源集中到一个项目中,该项目可以被需要这些"公共"资源的任何其他项目引用.例如,我有一个BMP图像,我在各个控件和窗口中使用单独的项目作为横幅/徽标.看起来我应该能够将此图像作为资源添加到公共资源项目中,并从我的其他项目中引用它,而不是将图像单独添加到需要它的每个项目中.如果这是可能的,它会是什么样子,我应该怎么做呢?如果我的想法很糟糕我会接受建议,但项目将会非常大,所以我不想在整个地方添加资源.
谢谢!
PS我已经搜索了这个主题了很多但是有很多垃圾回答来自那些不知道他们在做什么的人.鉴于我对WPF比较陌生,我宁愿直接回答我的问题.
我想在WPF中创建一个On/Off按钮,我想让它在用户点击它时改变它的外观(如果它是关闭,如果它关掉,则切换到打开)使用图像.我将要使用的图像添加到资源中:
<Window.Resources>
<Image x:Key="Off1" Source="/WPFApplication;component/Images/off_button.png" Height="30" Width="70" />
<Image x:Key="On1" Source="/WPFApplication;component/Images/on_button.png" Height="30" Width="70"/>
</Window.Resources>
Run Code Online (Sandbox Code Playgroud)
而事件代码是,"flag"是一个布尔局部变量,初始化为true:
private void OnOff1Btn_Click(object sender, RoutedEventArgs e)
{
if (flag)
{
OnOff1Btn.Content = FindResource("Off1");
flag = false;
}
else
{
OnOff1Btn.Content = FindResource("On1");
flag = true;
}
}
Run Code Online (Sandbox Code Playgroud)
现在我需要创建2个开/关按钮,它们的行为相同.当我尝试为第二个按钮使用相同的资源时,我得到了一个例外:
Specified element is already the logical child of another element. Disconnect it first.
Run Code Online (Sandbox Code Playgroud)
我可以在第二个按钮中使用相同的图像资源,还是必须将图像作为具有不同密钥的资源再次添加?
我正在尝试本地化我的程序,但我希望发送给开发人员的错误消息以英文显示.我无法找到一种方法来实现这一点,因为似乎如果在抛出错误时将UI文化设置为另一种语言,则会抛出该语言.由于我自己并没有编写这个程序,并且它非常大,我认为创建新的try catch块以尝试在发生错误或可能发生错误时将文化设置回英语是不切实际的.目前,CurrentCulture和DefaultThreadCurrentCulture在整个应用程序中始终设置为英语,而CurrentUICulture设置为最终用户的语言.
当我解决方法时,我目前有一个函数已经遍历一个错误列表(使用System.Resources.ResourceSets(我假设是Windows错误,但我还需要一种方法来查找.NET错误,以便我可以迭代这个字符串替换了其他语言中的匹配错误,并用它们的英语等价物替换它们,以便在应用程序崩溃时构建一个大的错误消息发送给开发人员.真的,我没有太多的翻译,因为大部分的message是一个服务器堆栈跟踪并显示抛出异常的位置.最大的问题是转换内部异常消息,有时是主异常消息,因为有时抛出的错误不会出现在ResourceSet中,有时会使用格式化项目,如'{0 }".
这是我到目前为止翻译剩余错误的代码.我仍在努力添加正则表达式模式来翻译使用"{0}"之类的错误,所以如果有人对此提出建议或更好的方法,我会很感激建议.
public static string TranslateExceptionMessageTest(string exmsg, Exception e, CultureInfo currentui)
{
CultureInfo test = Thread.CurrentThread.CurrentUICulture;
string matchingstr = "";
string newstr = exmsg;
string resourcecollection = "";
Assembly a = e.GetType().Assembly;
ResourceManager rm = new ResourceManager(a.GetName().Name, a);
ResourceSet rsOriginal = rm.GetResourceSet(currentui, true, true);
ResourceSet rsTranslated = rm.GetResourceSet(new CultureInfo("en-US"), true, true);
foreach (DictionaryEntry item in rsOriginal)
{
if (exmsg.Contains(item.Value.ToString()))
{
if (item.Key.ToString() == "Word_At") // sometimes with spanish errors this replaces words containing the letters 'en' with …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用该语句动态添加xaml资源文件,
Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri("resources/leaf_styles.xaml", UriKind.Relative) });
Run Code Online (Sandbox Code Playgroud)
这是抛出异常,无法找到资源'resources/leaf_styles.xaml'.
我将leaf_styles.xaml文件添加到资源文件夹下的项目中,BuildAction设置为"Content",CopyAlways设置为True.我仍然得到这个错误.有人可以帮我指出什么错?
附加信息 -
如果我把它作为绝对位置,它正常工作.
Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary() { Source = new Uri(@"D:\foo\trunk\bin\resources\leaf_styles.xaml", UriKind.Absolute) });
Run Code Online (Sandbox Code Playgroud) 我有一个Styles.xaml该集团很多ResourceDictionary的内线一个MergedDictionary.
我导入了Styles.xaml UserControl.Resources
<UserControl.Resources>
<ResourceDictionary Source="Dictionaries\Styles.xaml" />
</UserControl.Resources>
Run Code Online (Sandbox Code Playgroud)
但是当我尝试添加转换器时
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionaries\Styles.xaml" /> <--! Exception -->
</ResourceDictionary.MergedDictionaries>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</ResourceDictionary>
</UserControl.Resources>
Run Code Online (Sandbox Code Playgroud)
它提升了
ArgumentNullException:值不能为null.
参数名称:item
将转换器包装在另一个内部MergedDictionary无效.
我怎么解决这个问题?
谢谢你们!
我最终弄清楚了:它Exception是在.xaml文件中引发的,但是Visual Studio没有提供足够的信息来找到错误的行.
以下代码确实有效.
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionaries\Styles.xaml" />
</ResourceDictionary.MergedDictionaries>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</ResourceDictionary>
</UserControl.Resources>
Run Code Online (Sandbox Code Playgroud) wpf ×9
xaml ×6
c# ×5
.net ×3
.net-4.0 ×1
assemblies ×1
bitmapsource ×1
combobox ×1
converter ×1
dictionary ×1
exception ×1
image ×1
localization ×1
mvvm ×1
styles ×1