Search code examples
c#wpfxamlframeworkelementfactory

Converting ControlTemplate XAML to C#


I have been stumped with trying to convert the following code into pure c#. This XAML code is from Cavanaghs blog on how to make rounded corners on anything. The code works but I need to convert it to c# as i need it to be dynamic in some cases. If you could help that would be great.

<Setter Property="Template">
<Setter.Value>
    <ControlTemplate TargetType='{x:Type ListViewItem}'>
        <Grid>
            <Border CornerRadius="15" Name="mask" Background="White"/>
            <StackPanel Background="Beige">
                <StackPanel.OpacityMask>
                    <VisualBrush Visual="{Binding ElementName=mask}"/>
                </StackPanel.OpacityMask>
                <GridViewRowPresenter Content="{TemplateBinding Content}" Columns="{TemplateBinding GridView.ColumnCollection}"/>
                <TextBlock Background="LightBlue" Text="{Binding News}" />
            </StackPanel>
        </Grid>
    </ControlTemplate>
</Setter.Value>

So far I have the following but I am getting errors.

FrameworkElementFactory border = new FrameworkElementFactory(typeof(Border));
border.SetValue(Border.BackgroundProperty, Brushes.White);
border.SetValue(Border.CornerRadiusProperty, new CornerRadius(8, 8, 8, 8));
border.SetValue(Border.NameProperty, "roundedMask");

As far as I can tell I cant make the VisualBrush as a FrameworkElementFactory (crashes), but if i declare it as a regular element VisualBrush i cant pass border in as a Visual since its a FrameworkElementFactory.

Simply i am getting lost, any help would be appreciated. Thanks for any help


Solution

  • You do not want to know this. Seriously, you don't, it's a nightmare.

    Edit: If i did not make any mistake this is the translation of your code...

    Setter setter = new Setter();
    setter.Property = ListViewItem.TemplateProperty;
    ControlTemplate template = new ControlTemplate(typeof(ListViewItem));
    var grid = new FrameworkElementFactory(typeof(Grid));
    var border = new FrameworkElementFactory(typeof(Border));
    border.SetValue(Border.BackgroundProperty, Brushes.White);
    border.SetValue(Border.NameProperty, "mask");
    border.SetValue(Border.CornerRadiusProperty, new CornerRadius(15));
    grid.AppendChild(border);
    var stackPanel = new FrameworkElementFactory(typeof(StackPanel));
    stackPanel.SetValue(StackPanel.BackgroundProperty, Brushes.Beige);
    var visualBrush = new FrameworkElementFactory(typeof(VisualBrush));
    visualBrush.SetBinding(VisualBrush.VisualProperty, new Binding() { ElementName = "mask" });
    stackPanel.SetValue(StackPanel.OpacityMaskProperty, visualBrush);
    var gridViewRowPresenter = new FrameworkElementFactory(typeof(GridViewRowPresenter));
    gridViewRowPresenter.SetValue(GridViewRowPresenter.ContentProperty, new TemplateBindingExtension(GridViewRowPresenter.ContentProperty));
    gridViewRowPresenter.SetValue(GridViewRowPresenter.ColumnsProperty, new TemplateBindingExtension(GridView.ColumnCollectionProperty));
    stackPanel.AppendChild(gridViewRowPresenter);
    var textBlock = new FrameworkElementFactory(typeof(TextBlock));
    textBlock.SetValue(TextBlock.BackgroundProperty, Brushes.LightBlue);
    textBlock.SetBinding(TextBlock.TextProperty, new Binding("News"));
    stackPanel.AppendChild(textBlock);
    grid.AppendChild(stackPanel);
    template.VisualTree = grid;
    setter.Value = template;
    

    Edit: There is still a bug left, the VisualBrush cannot be created like that, the rest seems to work.