Reputation: 362
I've created a custom control that is styled and configures in its own XAML sheet. Databindings in this control uses a specific object (CProject class).
Just to clarify, the control is a project frame, that has controls for settings and a canvas that will be the workspace for each/any project.
The project control (IPProjectPanel) inherits "Frame", and also adds a "settings" stack panel to its children list which in turn contains controls for - well, settings.
The CProject class however, is the pure functional part, with no UI interaction or handling whatsoever. So, I need to "plug" an instance of CProject into every unique project that can be active. So, I want to set a specific instance of CProject as datacontext to every IPProjectPanel instance in a tabpanel. Either I want to set the datacontext by code, or have it created by settings datacontext in XAML, and retrieving it after it has been initialized.
The problem though, is that I cant quite figure out either.
Here is a snippet of the style of the IPProjectPanel in XAML, that uses the approach to set datacontext in XAML:
<Style TargetType="{x:Type ip:IPProjectGrid}">
<Setter Property="OverridesDefaultStyle"
Value="True" />
<Setter Property="SnapsToDevicePixels"
Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ip:IPProjectGrid}">
<Grid Background="White"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Margin="0">
<!---->
<Grid.DataContext>
<ipp:CProject></ipp:CProject>
</Grid.DataContext>
<StackPanel x:Name="PART_settingsPanel"
HorizontalAlignment="Right"
VerticalAlignment="Stretch"
MinWidth="300" Background="Gray">
<GroupBox Header="Project settings">
<StackPanel>
....
</style>
Here it is set as a context to Grid, but I'd like to have it as a context of the actual class (IPProjectPanel).
So, the IPProjectPanel instance is created by code (for now..), and I need to retrieve the CProject instance (or set one) so that I can work with it.
I'd like to keep to C#/WPF ways to do stuff, as this app is also training for WPF and C# concepts and such. So the "best C#-WPF" way to do it, is very welcome, but a solution either way!
Thank you for your time.
Upvotes: 0
Views: 3493
Reputation: 24453
The way you have this set up currently has the potential to create some nasty bugs. You should never declare a DataContext
object instance inside a template unless you never plan on accessing it outside of that template's scope. By doing so you will be creating a new instance of the CProject
class any time the control needs to be visually re-loaded (like changing tabs) and you may end up referencing an old CProject
instance in code while displaying a completely separate one on the screen. Declaring a DataContext
object not in a template (i.e. Window.DataContext
) is fine.
If you want each control instance to create its own CProject
instance you would be better off doing that in code in the constructor and exposing that as a property on the control which you can then bind your Grid.DataContext
to inside the template. Avoid setting it to the DataContext
property of the control itself as this will cause any implicit source Bindings that are set on the control where it is declared in XAML to break by overriding the inherited DataContext
:
Grid.DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=PropertyWithCProject}"
It's probably more likely that you will want to control the CProject
instances externally and hand them to the control instances. To do this you can create them in a container ViewModel class (MVVM pattern) and set this as a DataContext
higher up on something that will contain all of your custom controls. You can then expose individual CProjects
or a collection of them and bind your controls' DataContexts
to those.
Upvotes: 0
Reputation: 11439
So in general, the datacontext is primary inteded to be for your ViewModel, and in fact WPF is really set up for doing MVVM (Model View ViewModel) style applications. It's actually fairly simple to learn, but if you're looking for the "Best C#-WPF" way of doing things, take the time to learn MVVM. It's really fairly straightforward.
Simple Example from CodeProject:
http://www.codeproject.com/Articles/165368/WPF-MVVM-Quick-Start-Tutorial
From Microsoft (somewhat heavy reading):
http://msdn.microsoft.com/en-us/library/gg405484(v=pandp.40).aspx
Upvotes: 1