WPF :: 以不同于 RibbonGallery 的方式设置 RibbonComboBox 的样式
WPF :: Styling the RibbonComboBox Differently Than The RibbonGallery
我有一个用来设置字体大小的RibbonComboBox
。它有一个 RibbonGallery
列出了各种字体大小,显示在适当的 FontSize
:
<r:RibbonComboBox DataContext="{x:Static vm:RibbonDataModel.FontSizeComboBoxData}"
SelectionBoxWidth="30">
<r:RibbonGallery MaxColumnCount="1"
Command="{Binding Command}"
CommandParameter="{Binding SelectedItem}">
<r:RibbonGallery.GalleryItemTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding}"
FontSize="{Binding}" />
</Grid>
</DataTemplate>
</r:RibbonGallery.GalleryItemTemplate>
</r:RibbonGallery>
</r:RibbonComboBox>
编辑 这是我的 ViewModel:
public static RibbonDataModel
{
public static GalleryData<object> FontSizeComboBoxData
{
get
{
lock (LockObject)
{
const string key = "Font Size";
if (!DataCollection.ContainsKey(key))
{
var value = new GalleryData<object>
{
Command = HtmlDocumentCommands.ChangeFontSize,
Label = "Change Font Size",
ToolTipDescription = "Set the font to a specific size.",
ToolTipTitle = "Change Font Size",
};
var fontSizes = new GalleryCategoryData<object>();
var i = 9.0;
while (i <= 30)
{
fontSizes.GalleryItemDataCollection.Add(i);
i += 0.75;
}
value.CategoryDataCollection.Add(fontSizes);
DataCollection[key] = value;
}
return DataCollection[key] as GalleryData<object>;
}
}
}
}
一切都按预期工作,但在我 select 画廊中的项目之后,它显示在 RibbonComboBox
中,与它使用的一样大(或小)FontSize
在图库中。
"reset" selected 项目的 FontSize
如何在 RibbonComboBox
中显示为默认值?
我会建议您使用 Fluent.Ribbon 库而不是 Microsoft Ribbons(因为它们有很多错误,维护得不好并且只支持旧样式,真的相信我,它会拯救你好麻烦)。
那么您只需使用此代码即可:
<fluent:ComboBox Header="Font Size" ItemsSource="{Binding FontSizes}">
<fluent:ComboBox.ItemTemplate>
<ItemContainerTemplate>
<TextBlock FontSize="{Binding }" Text="{Binding }" />
</ItemContainerTemplate>
</fluent:ComboBox.ItemTemplate>
</fluent:ComboBox>
并得到想要的结果:
RibbonComboBox
使用 ContentPresenter
来显示您 select 在 RibbonGallery
中的项目。
此外,ContentPresenter
采用与您在 RibbonGallery
中声明的相同的 ItemTemplate
。
这就是您遇到问题的 "core" 原因。
因此您可以选择两种解决方案来解决问题。
第一个解决方案(最快的一个)
您只需将 RibbonComboBox 的 IsEditable
属性 设置为 "true"。通过这种方式,RibbonComboBox 将 ContentPresenter 替换为 TextBox,而无需使用任何 ItemTemplate。然后字体将具有正确的大小。
第二种解决方案(最好的一种恕我直言)
由于RibbonComboBox的ContentPresenter和RibbonGallery同时使用了ItemTemplate,这就是我们可以尝试解决问题的地方。 olny 的区别在于,当 DataTemplate 放在 RibbonGallery 内部时,它的父级是 RibbonGalleryItem
。
因此,如果其父级不是 RibbonGalleryItem
,您会自动知道 DataTemplate 位于 ContentPresenter 中。
您可以通过编写一个简单的 DataTrigger
来处理这种情况。
让我们在代码中看到所有内容。
我写了一个简化的ViewModel:
namespace WpfApplication1
{
public class FontSizes
{
private static FontSizes instance = new FontSizes();
private List<double> values = new List<double>();
public FontSizes()
{
double i = 9.0;
while (i <= 30)
{
values.Add(i);
i += 0.75;
}
}
public IList<double> Values
{
get
{
return values;
}
}
public static FontSizes Instance
{
get
{
return instance;
}
}
}
}
那么这是我的观点:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ribbon="http://schemas.microsoft.com/winfx/2006/xaml/presentation/ribbon"
xmlns:vm="clr-namespace:WpfApplication1"
Title="Window1" Height="300" Width="300">
<Window.Resources />
<DockPanel>
<ribbon:RibbonComboBox Label="Select a font size:"
SelectionBoxWidth="62"
VerticalAlignment="Center">
<ribbon:RibbonGallery MaxColumnCount="1">
<ribbon:RibbonGalleryCategory DataContext="{x:Static vm:FontSizes.Instance}" ItemsSource="{Binding Path=Values, Mode=OneWay}">
<ribbon:RibbonGalleryCategory.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock Name="tb" Text="{Binding}" FontSize="{Binding}" />
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ribbon:RibbonGalleryItem, AncestorLevel=1}}"
Value="{x:Null}">
<Setter TargetName="tb" Property="FontSize" Value="12" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ribbon:RibbonGalleryCategory.ItemTemplate>
</ribbon:RibbonGalleryCategory>
</ribbon:RibbonGallery>
</ribbon:RibbonComboBox>
</DockPanel>
</Window>
如您所见,DataTrigger 是 "component",它使 "dirty job".
现在您只需要考虑您喜欢哪种解决方案。
我有一个用来设置字体大小的RibbonComboBox
。它有一个 RibbonGallery
列出了各种字体大小,显示在适当的 FontSize
:
<r:RibbonComboBox DataContext="{x:Static vm:RibbonDataModel.FontSizeComboBoxData}"
SelectionBoxWidth="30">
<r:RibbonGallery MaxColumnCount="1"
Command="{Binding Command}"
CommandParameter="{Binding SelectedItem}">
<r:RibbonGallery.GalleryItemTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding}"
FontSize="{Binding}" />
</Grid>
</DataTemplate>
</r:RibbonGallery.GalleryItemTemplate>
</r:RibbonGallery>
</r:RibbonComboBox>
编辑 这是我的 ViewModel:
public static RibbonDataModel
{
public static GalleryData<object> FontSizeComboBoxData
{
get
{
lock (LockObject)
{
const string key = "Font Size";
if (!DataCollection.ContainsKey(key))
{
var value = new GalleryData<object>
{
Command = HtmlDocumentCommands.ChangeFontSize,
Label = "Change Font Size",
ToolTipDescription = "Set the font to a specific size.",
ToolTipTitle = "Change Font Size",
};
var fontSizes = new GalleryCategoryData<object>();
var i = 9.0;
while (i <= 30)
{
fontSizes.GalleryItemDataCollection.Add(i);
i += 0.75;
}
value.CategoryDataCollection.Add(fontSizes);
DataCollection[key] = value;
}
return DataCollection[key] as GalleryData<object>;
}
}
}
}
一切都按预期工作,但在我 select 画廊中的项目之后,它显示在 RibbonComboBox
中,与它使用的一样大(或小)FontSize
在图库中。
"reset" selected 项目的 FontSize
如何在 RibbonComboBox
中显示为默认值?
我会建议您使用 Fluent.Ribbon 库而不是 Microsoft Ribbons(因为它们有很多错误,维护得不好并且只支持旧样式,真的相信我,它会拯救你好麻烦)。
那么您只需使用此代码即可:
<fluent:ComboBox Header="Font Size" ItemsSource="{Binding FontSizes}">
<fluent:ComboBox.ItemTemplate>
<ItemContainerTemplate>
<TextBlock FontSize="{Binding }" Text="{Binding }" />
</ItemContainerTemplate>
</fluent:ComboBox.ItemTemplate>
</fluent:ComboBox>
并得到想要的结果:
RibbonComboBox
使用 ContentPresenter
来显示您 select 在 RibbonGallery
中的项目。
此外,ContentPresenter
采用与您在 RibbonGallery
中声明的相同的 ItemTemplate
。
这就是您遇到问题的 "core" 原因。
因此您可以选择两种解决方案来解决问题。
第一个解决方案(最快的一个)
您只需将 RibbonComboBox 的 IsEditable
属性 设置为 "true"。通过这种方式,RibbonComboBox 将 ContentPresenter 替换为 TextBox,而无需使用任何 ItemTemplate。然后字体将具有正确的大小。
第二种解决方案(最好的一种恕我直言)
由于RibbonComboBox的ContentPresenter和RibbonGallery同时使用了ItemTemplate,这就是我们可以尝试解决问题的地方。 olny 的区别在于,当 DataTemplate 放在 RibbonGallery 内部时,它的父级是 RibbonGalleryItem
。
因此,如果其父级不是 RibbonGalleryItem
,您会自动知道 DataTemplate 位于 ContentPresenter 中。
您可以通过编写一个简单的 DataTrigger
来处理这种情况。
让我们在代码中看到所有内容。
我写了一个简化的ViewModel:
namespace WpfApplication1
{
public class FontSizes
{
private static FontSizes instance = new FontSizes();
private List<double> values = new List<double>();
public FontSizes()
{
double i = 9.0;
while (i <= 30)
{
values.Add(i);
i += 0.75;
}
}
public IList<double> Values
{
get
{
return values;
}
}
public static FontSizes Instance
{
get
{
return instance;
}
}
}
}
那么这是我的观点:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ribbon="http://schemas.microsoft.com/winfx/2006/xaml/presentation/ribbon"
xmlns:vm="clr-namespace:WpfApplication1"
Title="Window1" Height="300" Width="300">
<Window.Resources />
<DockPanel>
<ribbon:RibbonComboBox Label="Select a font size:"
SelectionBoxWidth="62"
VerticalAlignment="Center">
<ribbon:RibbonGallery MaxColumnCount="1">
<ribbon:RibbonGalleryCategory DataContext="{x:Static vm:FontSizes.Instance}" ItemsSource="{Binding Path=Values, Mode=OneWay}">
<ribbon:RibbonGalleryCategory.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock Name="tb" Text="{Binding}" FontSize="{Binding}" />
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ribbon:RibbonGalleryItem, AncestorLevel=1}}"
Value="{x:Null}">
<Setter TargetName="tb" Property="FontSize" Value="12" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ribbon:RibbonGalleryCategory.ItemTemplate>
</ribbon:RibbonGalleryCategory>
</ribbon:RibbonGallery>
</ribbon:RibbonComboBox>
</DockPanel>
</Window>
如您所见,DataTrigger 是 "component",它使 "dirty job".
现在您只需要考虑您喜欢哪种解决方案。