Reputation: 466
I need a part of my Page
unmovable, so I thought using a Frame
, something like:
<StackPanel>
<Label Style="{StaticResource OneThirdColumnLabel}">Administrar papéis: Alterar papéis</Label>
<ItemsControl x:Name="PapeisIc">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Frame x:Name="_papeisAddFrame" Source="PapeisAdd.xaml" Height="50"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
Then, the Frame
would contain a Page
with:
<ScrollViewer VerticalScrollBarVisibility="Visible">
<StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,0,0,10">
<Label Style="{StaticResource LaterLabel}">Papel:</Label>
<TextBox Text="{Binding Papel}" Style="{StaticResource StdTextBox}" Width="100" />
<Label Style="{StaticResource LaterLabel}">Descrição:</Label>
<TextBox Text="{Binding Descricao}" Style="{StaticResource StdTextBox}" Width="400" />
<Button x:Name="DeleteFieldBtn" Style="{StaticResource deleteFieldButtom}" ToolTip="Eliminar este papel"/>
</StackPanel>
</StackPanel>
</ScrollViewer>
In the code-behind, the line:
PapeisIc.ItemsSource = _papeis;
Binds a object that's an ObservableCollection
of 3 items and I need it to display the 3 elements in the example.
What I get is:
So that, somehow it knows that there are 3 elements, but it doesn't bind it right...
I already tried to pass to the Page
the data as a parameter, but it didn't work either.
How can I bind those values?
Just to make it clear, I'm trying to bind to an ObservableCollection
of:
public class Role
{
public int Id { get; set; }
public string Papel { get; set; }
public string Descricao { get; set; }
}
Upvotes: 0
Views: 266
Reputation: 22079
The Frame
control does not pass the DataContext
down to the Page
. The easiest way to solve this issue is to remove the Frame
and move its content directly to the DataTemplate
.
If you really need the Frame
, you have to listen to the LoadCompleted
and DataContextChanged
events and propagate the DataContext
manually to the content of the Frame
. I show you how to do it with a TriggerAction
using the Microsoft.Xaml.Behaviors.Wpf
NuGet package.
public class UpdateContentDataContextAction : TriggerAction<Frame>
{
protected override void Invoke(object parameter)
{
if (AssociatedObject.Content is FrameworkElement frameworkElement)
frameworkElement.DataContext = AssociatedObject.DataContext;
}
}
<DataTemplate>
<Frame x:Name="_papeisAddFrame" Source="PapeisAdd.xaml" Height="50">
<b:Interaction.Triggers>
<b:EventTrigger EventName="LoadCompleted">
<local:UpdateContentDataContextAction/>
</b:EventTrigger>
<b:EventTrigger EventName="DataContextChanged">
<local:UpdateContentDataContextAction/>
</b:EventTrigger>
</b:Interaction.Triggers>
</Frame>
</DataTemplate>
If you want to do it in the code-behind, subscribe the events on the control and use the code of the trigger action.
<Frame x:Name="_papeisAddFrame" Source="PapeisAdd.xaml" Height="50" LoadCompleted="OnLoadCompleted" DataContextChanged="OnDataContextChanged">
private void OnLoadCompleted(object sender, NavigationEventArgs e)
{
PropagateDataContext((Frame)sender);
}
private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
PropagateDataContext((Frame)sender);
}
private void PropagateDataContext(Frame frame)
{
if (frame.Content is FrameworkElement frameworkElement)
frameworkElement.DataContext = frame.DataContext;
}
Upvotes: 1