I'm working on a large plugin component to a quite larger application. 90% of this particular View component is extremely dynamic (database driven) and done programmatically. There is a particular reason for that (minimal XAML), so think outside the box. And no, I can't go back and retool a code base that consists of 1000's of lines of code...that's a future version.
I can set values, bindings and add handlers, via the FrameworkElementFactory, but need to access the control itself to do other tasks. One task would be to add a ToolTipService to each FrameworkElement. I'm able to do it if I add a Loaded Event to each derived control, then manage it through the handler by adding it to an indexed object collection, but this is a really ugly way of doing it.
I put together this small snippet (below) for testing, but it encompasses the issue at hand.
MainWindow.xaml
<Window x:Class="FrameworkElementFactory_Control_Testing.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FrameworkElementFactory_Control_Testing"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="500"
Height="300"
mc:Ignorable="d">
<Grid>
<StackPanel x:Name="LayoutRoot"
Margin="5"
Orientation="Vertical" />
</Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Windows;
using System.Windows.Controls;
using System.Collections.ObjectModel;
namespace FrameworkElementFactory_Control_Testing
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
GridObjectCollection = new ObservableCollection<GridObject>() { new GridObject() };
//GridObjectCollection.Add(new GridObject());
DoTheGrid();
}
public ObservableCollection<GridObject> GridObjectCollection { get; set; }
public GridObject CurrentGridObject { get; set; }
private void DoTheGrid()
{
DataGrid dg = new DataGrid();
dg.Margin = new Thickness(5);
dg.AutoGenerateColumns = false;
dg.CanUserAddRows = false;
dg.CanUserDeleteRows = false;
dg.CanUserSortColumns = false;
dg.IsReadOnly = true;
dg.ColumnWidth = new DataGridLength(1, DataGridLengthUnitType.Auto);
dg.SelectionMode = DataGridSelectionMode.Single;
dg.SelectedItem = CurrentGridObject;
dg.ItemsSource = GridObjectCollection;
DataGridTemplateColumn dgTemplateColumn = new DataGridTemplateColumn();
FrameworkElementFactory factoryControl = null;
TextBlock headerName = new TextBlock() { Text = "Button Type" };
dgTemplateColumn.Header = headerName;
factoryControl = new FrameworkElementFactory(typeof(Button));
factoryControl.SetValue(Button.MarginProperty, new Thickness(1));
factoryControl.SetValue(Button.WidthProperty, Convert.ToDouble("70"));
factoryControl.SetValue(Button.HeightProperty, Convert.ToDouble("24"));
factoryControl.SetValue(Button.NameProperty, "btnCLICK_ME");
factoryControl.SetValue(Button.ContentProperty, "Click Me");
factoryControl.AddHandler(Button.LoadedEvent, new RoutedEventHandler(ButtonLoaded_Click));
DataTemplate cellTemplateControl = new DataTemplate();
cellTemplateControl.VisualTree = factoryControl;
dgTemplateColumn.CellTemplate = cellTemplateControl;
dgTemplateColumn.CanUserSort = false;
dg.Columns.Add(dgTemplateColumn);
this.LayoutRoot.Children.Add(dg);
}
private void ButtonLoaded_Click(object sender, RoutedEventArgs e)
{
Button btn = sender as Button;
//add btn to indexed collection for future reference (this is lame)
}
}
}
GridObject.cs
namespace FrameworkElementFactory_Control_Testing
{
public class GridObject
{
public GridObject()
{ }
}
}
Any constructive help is greatly appreciated. Thanks for your time folks.
CT