Binding beyond the DataContext - c#

I have a DataTemplate for templating my ItemsControl's items which are TimeSheet's Details.
I have couple of TextBox representing certain values of my TimeSheet's Details but their IsEnabled property depends on the TimeSheet itself, not the details.
<ItemsControl
ItemsSource="{Binding Path=TimeSheet.TimeSheetDetails}"
ItemTemplate="{StaticResource TimeSheetDetail}"
/>
<DataTemplate x:Key="TimeSheetDetail">
<TextBox
Text="{Binding Houre}"
IsEnabled="Binding ??????">
</DataTemplate>
Since the IsEnabled property cant be found in the TimeSheetDetails but can be found in my ViewModel, i would like to bind directly to my ViewModel's Property but when i try binding, to my ViewModel from my DataTemplate, it only seems to look in my TimeSheetDetail.
How can i access my ViewModel's public property directly?

You can bind to your parent's DataContext:
{Binding DataContext.IsEnabled,
RelativeSource={RelativeSource FindAncestor, AncestorType=ItemsControl}}

Related

Custom control binding is not updating

I'm having trouble getting my binding to work correctly. Basically I have this, call this Control1.xaml. The commented out portion of the code binds correctly and updates as expected.
<progControls:CalibrationSummary
</progControls:CalibrationSummary>
<!--<TextBlock Text="{Binding Path=NumberOfCalibrations, Mode=OneWay}"/>-->
However, if I put that commented code in a custom control called CalibrationsSummary.xaml, I cannot bind this to NumberOfCalibrations.
Here's what CalibrationsSummary looks like
<Grid>
<TextBlock Text="{Binding Path=NumberOfCalibrations, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"/>
</Grid>
Note that I do use RelativeSource to try to get the property associated with Control1.xaml, tried TemplateBinding also. What am I doing wrong?
CalibrationSummary has no TemplatedParent unless you have put it in a ControlTemplate.
If you don't explicitly set the DataContext of the property of CalibrationSummary somewhere, it will inherit the DataContext from its parent control (which I assume is Control1) and then you can bind any property of this control's DataContext as usual without specifying any source:
<Grid>
<TextBlock Text="{Binding Path=NumberOfCalibrations}"/>
</Grid>

WPF ItemsControl binding not updating when bound to an ObservableCollection in an object in the View Model

Basically I have an object in my view model that contains an ObservableCollection of a custom object. My XAML's DataContext is set to my ViewModel, my ViewModel contains a 'Scratchdisk' object, and the Scratchdisk object contains an ObservableCollection of Frame objects. Both the Scratchdisk and the Collection are set up as DependencyProperties.
In short: XAML --DataContext--> EditorViewModel --DependencyProperty--> Scratchdisk --DependencyProperty--> ObservableCollection<Frame>
The Frame object has 3 standard properties: Index, Image, and ImageUrl.
I'm trying to bind to the ObservableCollection in my XAML using this code:
<ItemsControl DataContext="{Binding Source=ThumbnailScratchdisk}" ItemsSource="{Binding Frames, UpdateSourceTrigger=PropertyChanged}" ItemTemplate="{StaticResource ThumbnailTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal"></VirtualizingStackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Where ThumbnailTemplate is defined in Window Resources as:
<DataTemplate x:Key="ThumbnailTemplate">
<Image Width="128" Height="96" Source="{Binding ImageUrl}"/>
</DataTemplate>
Theoretically, what should happen is, the Scratchdisk should receive filenames, create Frame objects, add them to the Collection, and then the binding should display them. The ObservableCollection is working and being populated, but the binding doesn't seen to be updating. All the updatable properties are set as DependencyProperties so the binding should update shouldn't it?
Links to the files:
XAML
ViewModel
Scratchdisk
Frame
The problem is in the binding of the DataContext of your ItemsControl.
You're setting it to "{Binding Source=ThumbnailScratchdisk}", but what you (presumably) want is to set it to just "{Binding ThumbnailScratchdisk}".
The DataContext of the page is already an instance of EditorViewModel, and you want the DataContext for the ItemsControl to bind to the property ThumbnailScratchdisk of that viewmodel.
Trying changing the binding path in XAML to ThumbnailScratchdisk.Frames

Partial TreeView refresh after EF model ItemsSource update

I have an Entity Framework model and TreeView which has a binding with model.
in constructor:
Context.TestCategory.Load();
my TreeView:
<TreeView x:Name="DbTree" ItemsSource="{Binding Context.TestCategory.Local}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Tests}" >
<TextBlock Text="{Binding Name}" ContextMenuOpening="ContextMenu_ContextMenuOpening">
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem Header="Добавить тест" Click="TestAdd" CommandParameter="{Binding
RelativeSource={RelativeSource
AncestorType={x:Type ContextMenu}}}"></MenuItem>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
........................................
other items
........................................
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
After updating items in ItemsSource I need to update the related TreeView branch, what is the best way to do this?
I'm not sure binding your ItemsSource directly to a context property is a great thing to do.
What you're supposed to do with binding is bind to a property that can do RaisePropertyChanged when it has changed, and then the UI elements will update if needed. I use MVVM so my binding is all from a ViewModel which is the datacontext for the View, and which implements the INotifyPropertyChanged interface. Then within that my property setter can look like this:
private List<TestCategories>_myItemSourceList;
public List<TestCategories> MyItemSourceList
{
get { return _myItemSourceList; }
set
{
if (value != _myItemSourceList)
{
_myItemSourceList= value;
RaisePropertyChanged(() => MyItemSourceList);
}
}
}
And the XAML would look like ...
<TreeView x:Name="DbTree" ItemsSource="{Binding MyItemSourceList}">
Obviously because you're not using MVVM your code will be slightly different, but the principle remains: bind your ItemSource to a property that can RaisePropertyChanged.
EDIT: My RaisePropertyChanged is within the Prism framework, so is using a lambda, but the 'standard' was is with a string like this RaisePropertyChanged("MyItemSourceList")

WPF Command Binding to ancestor property

I have a doubt about binding to an ancestor property in WPF. My situation is: my window has a view model as data context with all the commands as ICommand properties. I have a list of checkboxes as follows:
<ItemsControl ItemsSource="{Binding CurrentCustomer.SuppiersSelection}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<CheckBox FontSize="16" Content="{Binding Path=Supplier.Company}"
IsChecked="{Binding Path=Selected}"></CheckBox>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
The question is: I want that each checkbox has a command bound to it, so that when a supplier is checked or unchecked the relationship between customer and supplier is automatically saved. My problem is that the command properties are on the Window Data Context and this checkboxes is using as data context the ItemsSource of ItemControl. How do I bind to the property on the Window Data Context?
Thanks in advance for your help.
{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}, Path=DataContext}
But it's not clear what is the task.
Why don't you use two way binding and process the change of property Selected?

MVC design issue

I'm having an application using MVC. It has a canvas and property grid. When an item is selected in the canvas. The property grid should display its details.
So I made an event listener and when item is selected in the canvas it raises an event to the controller which pass the selected item to the property grid to display the details.
Model :
Item object containing name, description
Controller :
protected Controller(object model, FrameworkElement view)
{
this._model = model;
this._view = view;
}
public virtual void Initialize()
{
View.DataContext = Model;
}
View :
<TextBlock>Status</TextBlock>
<ComboBox ItemsSource="?????"/>
Where view is the property grid and model is the selected item.
The problem is in the property grid there is a dropdown list containing lookup values how can I get the dropdown values given that the datacontext of the property grid has already been set to the selected item which doesn't contain reference to these lookup items.
I know that it's easy to use custom code to do that. But I don't want to violate the MVC aproach.
Bind to a source rather than DataContext, sources are provided by ElementName, RelativeSource & Source, so you can name the View for example and use ElementName to get it as source then the Path could be DataContext.LookupValues or whatever your property in the model (- the DataContext of the View is your model -) is called.
e.g.
<Window ...
Name="Window">
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Name}" />
<ComboBox ItemsSource="{Binding ElementName=Window, Path=DataContext.Occupations}"
SelectedItem="{Binding Occupation}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<!-- ... --->
Edit: Your problem seems to be that you do not pass the information you need, consider a design which still grants you access to more than just the SelectedItem of some list, e.g.
<Window ...
Name="Window">
<ListBox Name="listBox" ItemsSource="{Binding Data}" />
<ContentControl DataContext="{Binding ElementName=listBox, Path=SelectedItem}">
<ComboBox ItemsSource="{Binding ElementName=Window, Path=DataContext.Occupations}"
SelectedItem="{Binding Occupation}" />
</ContentControl>
<!-- ... --->
The DataContext of the ContentControl may be the SelectedItem of the ListBox but the ComboBox inside can still reference the DataContext of the Window which should provide the necessary information.
This is similar to my first example in that the DataContext inside the DataTemplate is always an item of the collection but you can access external DataContexts using sources in your bindings.

Categories

Resources