I have a ViewModel
class FontsViewModel : ObservableObject
{
public FontsViewModel()
{
InitFonts();
}
public ObservableCollection<Typeface> Fonts
{
get;
private set;
}
protected void InitFonts()
{
Fonts = (ObservableCollection<Typeface>)System.Windows.Media.Fonts.SystemFontFamilies;
}
}
and i bind it in XAML
<ribbon:RibbonComboBox.DataContext>
<vm:FontsViewModel />
</ribbon:RibbonComboBox.DataContext>
<ribbon:RibbonGallery>
<ribbon:RibbonGalleryCategory ItemsSource="{Binding Fonts}">
<ribbon:RibbonGalleryCategory.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" FontFamily="{Binding}" />
</DataTemplate>
</ribbon:RibbonGalleryCategory.ItemTemplate>
</ribbon:RibbonGalleryCategory>
</ribbon:RibbonGallery>
when i try running, i get
System.Windows.Markup.XamlParseException occurred
Message='The invocation of the constructor on type 'MarkdownEditMVVM.ViewModels.FontsViewModel' that matches the specified binding constraints threw an exception.' Line number '57' and line position '26'.
Source=PresentationFramework
LineNumber=57
LinePosition=26
StackTrace:
at System.Windows.Markup.XamlReader.RewrapException(Exception e, IXamlLineInfo lineInfo, Uri baseUri)
at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri)
at System.Windows.Markup.WpfXamlLoader.LoadBaml(XamlReader xamlReader, Boolean skipJournaledProperties, Object rootObject, XamlAccessLevel accessLevel, Uri baseUri)
at System.Windows.Markup.XamlReader.LoadBaml(Stream stream, ParserContext parserContext, Object parent, Boolean closeStream)
at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
at MarkdownEditMVVM.MainWindow.InitializeComponent() in d:\Projects\MarkdownEdit\MarkdownEditMVVM\MainWindow.xaml:line 1
at MarkdownEditMVVM.MainWindow..ctor() in D:\Projects\MarkdownEdit\MarkdownEditMVVM\MainWindow.xaml.cs:line 25
InnerException: System.InvalidCastException
Message=Unable to cast object of type 'System.Collections.ObjectModel.ReadOnlyCollection`1[System.Windows.Media.FontFamily]' to type 'System.Collections.ObjectModel.ObservableCollection`1[System.Windows.Media.Typeface]'.
Source=MarkdownEditMVVM
StackTrace:
at MarkdownEditMVVM.ViewModels.FontsViewModel.InitFonts() in D:\Projects\MarkdownEdit\MarkdownEditMVVM\ViewModels\FontsViewModel.cs:line 26
at MarkdownEditMVVM.ViewModels.FontsViewModel..ctor() in D:\Projects\MarkdownEdit\MarkdownEditMVVM\ViewModels\FontsViewModel.cs:line 15
InnerException:
what am i doing wrong? its like a modified version of what i see on L开发者_Python百科esters Tutorial on WPF Ribbon
You cannot convert a SystemFontFamilies to an ObservableCollection. Instead instantiate a new collection:
Fonts = new ObservableCollection<Typeface> (Fonts.SystemFontFamilies);
edit: The above code has a mismatch between the property type and the collection type.
Instead use one of the below:
var myFonts = new ObservableCollection<FontFamily>(Fonts.SystemFontFamilies);
var typefaces = new ObservableCollection<Typeface>(Fonts.SystemTypefaces);
Two points:
You really don't need an ObservableCollection here (if the list of Fonts will never change.) It's sufficient to expose an
IEnumerable<Typeface>
property.You really shouldn't be referencing a View-specific object like a Typeface from a ViewModel. It would be better to expose the available font names as strings and inject the available names through some service interface. The service interface (on the View side) would then call
System.Windows.Media.Fonts.SystemFontFamilies
and cast to string names. This gives you isolation for testability (your unit tests can supply their own font names.)
精彩评论