Passing DataContext to User Control in WPF - wpf

I have a usercontrol that acts as a container for a ContentControl.
The user control container has a listview control that I want to use to update controls in a dynamically added user control assigned to the ContentControl.
IOW, as I scroll through the listview control, the textbox's in the UC assigned to the ContentControl should update.
I've done this when everything is in one page no problem, but am having a hard time passing the ListView as a datacontext to the dynamically added UC.
How can this be done?
In XAML
<ListView x:name="lstIncidents">
</Listview>
<ContentControl x:Name="PlaceHolder"></ContentControl>
In Codebehind...
PlaceHolder.Content = new LocationView();
When adding the "LocationView" to the PlaceHolder.Content, I need to pass "lstIncidents" as the datacontext so the textboxs in "LocationView" refresh as the ListView is navigated.

Controls inherit their DataContext from their parent, so try setting the DataContext on the ContentControl:
<ContentControl
x:Name="PlaceHolder"
DataContext="{Binding SelectedItem,ElementName=lstIncidents}" />

Related

wpf pass datatemplate to new window

i need to send a DataTemplate to a new window for printing purposes.
1) I have create a general Window lets name it PrintPreview that holds the followings:
FlowDocument > BlockUiContainer > ContentControl (Responsible to display the DataTemplate that i will send to it)
The problem is that the bindings inside the datatemplate are not working. (not for all cases )
For example:
i have this datatemplate somewhere in my application
<DataTemplate x:Key="MyPrintPreview">
<DockPanel>
<TextBlock Text="{Binding SomeProperty1,RelativeSource={RelativeSource AncestorType=UserControl}}"></TextBlock>
<TextBlock Text="{Binding Source={StaticResource SomeViewModel},Path=SomeProperty2}"></TextBlock>
</DockPanel>
</DataTemplate>
The above DataTemplate is working very well and show both properties in my current View (UserControl)
but when i send this DataTemplate to the New Window PrintPreview i have the following issues
The 1st TextBlock (SomeProperty1) fails to display the content
The 2nd TextBlock (SomeProperty2) show just fine!
i don't know how to make this work. or if am doing it the wrong way?
You should set or bind the Content property of the ContentControl to an object that contains the properties that the elements in the ContentTemplate try to bind to.
So set the ContentTemplate property of the ContentControl to your DataTemplate and set the Content property to the actual object to bind to. That's how a ContentControl is supposed to be used.
Also note that for your first binding to work, the ContentControl must be a child of a UserControl because you are binding to SomeProperty1 of the parent UserControl. If there is no parent UserControl, the binding will always fail.

Showing UserControl once at the time with DataTemplateSelector

I have a couple specific user controls to Show some Content, e.g. simple like Image, WebControl but also two complex specific custom controls drawing on a canvas.
Now I thought using the DataTemplateSelector to handle the different UserControls. I actully used this http://tech.pro/tutorial/807/wpf-tutorial-how-to-use-a-datatemplateselector as a reference.
I changed the code so the form loads the UserControls dynamically (according to the file extension) in the following collection:
ObservableCollection<string> _pathCollection = new ObservableCollection<string>();
The only difference to the reference is now I want to navigate back and forward to the next control by showing one control only at the time. Which control should I use instead of ListView?
<Grid>
<ListView ScrollViewer.CanContentScroll="False"
ItemsSource="{Binding ElementName=This, Path=PathCollection}"
ItemTemplateSelector="{StaticResource imgStringTemplateSelector}">
</ListView>
</Grid>
How do I need to bind it to the template (equal to ItemTemplateSelector above)? WPF is still very new to me and I am learning.
Use a ContentControl. Bind your current item to the Content-property and the DataTemplateSelector to the ContentTemplateSelector-property.
<ContentControl Content="{Binding Path=CurrentItem, Mode=OneWay}", ContentTemplateSelector="{StaticResource imgStringTemplateSelector}" />
Your CurrentItem should be a DependencyProperty or a INotifyPropertyChanged-property of your DataContext. When you change your CurrentItem, the ContentControl will update the template automatically with help of your TemplateSelector.

WPF Create user control dynamically on change of observablecollection OR Visualize nested ObservableCollections by using nested User controls

I am new to WPF, and I can't find a solution to my problem.
I've got an Observable Collection in my ViewModel:
ObservableCollection<Process>
Within the Process class is another ObervableCollection:
ObservableCollection<BurstTime>
I want to add a new User control (what can vizualize the actual state of Process data, and it's burst times) dynamically to one of my StackPanel in my view each time, when a new Process is activated, and remove it when the process is ended (when the observable collection changes).. During it's run, I want to diplay it's Burst Time collection, what can change in time..
I've tried to subscribe to the CollectionChanged event in my user control's codebehind and use a User Control inside another User Control and dynamicalli create required TextBlocks when my event handler runs, but I always get a System.Reflection.TargetInvocationException (inner exception: System.NullReferenceException) when my outer InitializeComponent() is running..
public ResourceUseView()
{
InitializeComponent();
((ObservableCollection<Process>)DataContext).CollectionChanged += ResourceUseView_CollectionChanged;
}
Is it possible to do it? Is it possible to create or remove User controls in my outer UserControl's codebehind while reacting to ObservableCollection's element changes, and update the outer when an element changes in the inner ObservableCollection? Are there other ways than instantiate a UserControl inside another User Control dynamically? Is there any special control, what can display ObservableCollection in ObservableCollection?
(If it'is possible, I would like to have different user controls as much as elements my ObservableCollection have..)
Thanks for your help!
The constructor runs before the data binding, so you are probably seeing that error because the DataContext is null at the time the constructor runes.
To bind to a collection, use a control that contains an ItemsSource property. And if you want to bind to a nested collection, modify the ItemTemplate of the control to use another control with an ItemsSource property for the nested collection.
Here's an example using an ItemsControl
<ItemsControl ItemsSource="{Binding Processes}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <ItemsControl ItemsSource="{Binding BurstTimes}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
I have some examples of the ItemsControl on my blog if you're interested.
If you want to specify a UserControl for each object, then set the ItemTemplate for the first ItemsControl to be the ProcessUserControl, and inside the ProcessUserControl have an ItemsControl bound to BurstTimes and use a BurstTimeUserControl for it's ItemTemplate
<ItemsControl ItemsSource="{Binding Processes}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:ProcessUserControl />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
...
<UserControl x:Class="MyNamespace.ProcessUserControl ...>
...
<ItemsControl ItemsSource="{Binding BurstTimes}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:BurstTimeUserControl />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
...
</UserControl>

setting data context of silverlight user control leaves the control as always visible

I have a 'searchwin.xaml' user control in a Silverlight page called Mainpage.xaml. 'searchwin' has its own viewmodel 'searhwinVM'. I have set searchwin's datacontext to its viewmodel in the Mainpage xaml like this
<UserControl.Resources>
<vm:SearchWin x:Name="SearchWinVM" x:Key="SearchWinVM" /> </UserControl.Resources>
<part:SearchWin ..... {other properties here}
Visibility="{Binding Converter={StaticResource BooleanToVisibilityConverter}, Path=IsSearchVisible}"
DataContext="{StaticResource SearchWinVM}"/>
This search control I want to set as invisible by default and visible only when I change to a particular value in my listbox which is on the mainpage.xaml. Setting the datacontext of the UC in the mainpage.xaml or programatically in the mainpage.xaml.cs causes the control to always be visble. I cant get it to hide now. If I remove the datacontext it works well as expected. Any ideas how to fix this?
Thanks for your time...
Have you verified that your converter is being called at all? I'd just put a breakpoint in and see what happens.

Binding to an element within a UserControl

Say I have a user control like the one below, how would I bind something to the ActualWidth of the "G1" grid from outside of the control?
<UserControl x:Class="Blah">
<WrapPanel>
<Grid x:Name="G1">
...
</Grid>
<Grid>
...
</Grid>
</WrapPanel>
</UserControl>
If you mean with outside the control, not as Content of the control, you can use ElementName in the Binding like so:
{Binding ElementName=G1, Path=ActualWidth}
If you mean outside the control in another Xaml file, then you can try to use the Path property if your control is in the scope of the other control:
{Binding ElementName=ParentControl, Path=G1.ActualWidth}
However I would advise against this design, because you may change the name of G1 one day, and you would never know of any bindings that might break.
If you want to bind to an external control where you use this user control, declare a DependencyProperty at your UserControl code behind and then Bind G1 to that property.
And bind the external control's property to the UserControl's DependencyProperty.
It is like a 2 level of indirection.

Resources