Content doesn't show on ToggleButton styled and templated in code
I found myself needing to define some styles and templates for a couple ToggleButton elements that I'm using in one of my programs. I have everything working, except that whatever I set as the content on them doesn't show. I'm at a loss as to how to get my contents to display correctly. My code is as follows:
private Style m_ToggleStyle;
private Style ToggleStyle
{
get
{
if (m_ToggleStyle == null)
{
lock (new object())
{
if (m_ToggleStyle == null)
{
m_ToggleStyle = new Style(typeof(ToggleButton));
m_ToggleStyle.Setters.Add(new Setter { Property = ToggleButton.TemplateProperty, Value = ToggleTemplate });
}
}
}
return m_ToggleStyle;
}
}
private ControlTemplate m_ToggleTemplate;
private ControlTemplate ToggleTemplate
{
get
{
if (m_ToggleTemplate == null)
{
lock (new object())
{
if (m_ToggleTemplate == null)
{
m_ToggleTemplate = new ControlTemplate();
FrameworkElementFactory g = new开发者_StackOverflow FrameworkElementFactory(typeof(Grid));
g.SetValue(Grid.MarginProperty, new Thickness(0));
g.Name = "MainGrid";
FrameworkElementFactory cp = new FrameworkElementFactory(typeof(ContentPresenter));
cp.SetValue(ContentPresenter.NameProperty, "Contents");
cp.SetValue(ContentPresenter.HorizontalAlignmentProperty, System.Windows.HorizontalAlignment.Stretch);
cp.SetValue(ContentPresenter.VerticalAlignmentProperty, System.Windows.VerticalAlignment.Stretch);
cp.SetValue(ContentPresenter.MarginProperty, new Thickness(2));
cp.Name = "Contents";
g.AppendChild(cp);
m_ToggleTemplate.VisualTree = g;
ImageBrush ibBackgroundUnselected = new ImageBrush();
ibBackgroundUnselected.ImageSource = new BitmapImage(new Uri("pack://application:,,,/Controls;component/Resources/TabUnselected.png", UriKind.Absolute));
g.SetValue(Grid.BackgroundProperty, ibBackgroundUnselected);
ImageBrush ibBackgroundSelected = new ImageBrush();
ibBackgroundSelected.ImageSource = new BitmapImage(new Uri("pack://application:,,,/Controls;component/Resources/TabSelected.png", UriKind.Absolute));
Trigger tIsChecked = new Trigger { Property = ToggleButton.IsCheckedProperty, Value = true };
tIsChecked.Setters.Add(new Setter(Grid.BackgroundProperty, ibBackgroundSelected, "MainGrid"));
m_ToggleTemplate.Triggers.Add(tIsChecked);
}
}
}
return m_ToggleTemplate;
}
}
This is used as I dynamically create ToggleButtons like:
ToggleButton tbExample = new ToggleButton();
tbExample.Style = ToggleStyle;
tbExample.Content = "Content";
I'm not seeing the line where you assign the VisualTree
of m_ToggleTemplate
. You have this line:
m_LocationSelectionTemplate.VisualTree = g;
But nowhere in your ToggleTemplate
accessor do you actually set a valid value for m_ToggleTemplate
.
Something else to note is your use of FrameworkElementFactory
. According to MSDN, this is not the best way to create control templates, and is in fact deprecated:
This class is a deprecated way to programmatically create templates, which are subclasses of FrameworkTemplate such as ControlTemplate or DataTemplate; not all of the template functionality is available when you create a template using this class. The recommended way to programmatically create a template is to load XAML from a string or a memory stream using the Load method of the XamlReader class.
FrameworkElementFactory cp = new FrameworkElementFactory(typeof(ContentPresenter));
cp.SetValue(ContentPresenter.NameProperty, "Contents");
// try adding this line
cp.SetValue(ContentPresenter.ContentSourceProperty, "Content");
Found the problem:
m_ToggleTemplate = new ControlTemplate();
Should have been:
m_ToggleTemplate = new ControlTemplate(typeof(ToggleButton));
Apparently if you don't set the type of the ControlTemplate, it only partially works.
精彩评论