Hallo and thank you for your time.
I have a peculiar problem. I have created a usercontol, which has some custom dependency properties.
If i implement the usercontrol, and bind to a static text. Everything is working fine.
However, if i try to set it to the value of a selected objects properties. It does not work.
This is the error i am getting in the output window:
Error: BindingExpression path error: 'SelectedUseCase' property not
found on 'Helper.UserControls.UseCasePropertyDisplay'.
BindingExpression: Path='SelectedUseCase.Name'
DataItem='Helper.UserControls.UseCasePropertyDisplay'; target element
is 'Helper.UserControls.UseCasePropertyDisplay' (Name='null'); target
property is 'Text' (type 'String')
UserControl:
https://github.com/Toudahl/SoftwareDesignHelper/blob/master/Helper/UserControls/DisplayAndEditControl.xaml
<UserControl
x:Class="Helper.UserControls.UseCasePropertyDisplay"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Helper.UserControls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<StackPanel Orientation="Horizontal"
Margin="260,0,0,0">
<TextBlock Text="{Binding Label}"
Style="{StaticResource UseCaseTextBlock}"
x:Name="textblock_label"/>
<TextBlock x:Name="textblock_propertyContent"
Text="{Binding Text}"
Style="{StaticResource UseCaseFrameWorkTextElement}"
DoubleTapped="textblock_DoubleTapped" />
<TextBox x:Name="textbox_propertyContent"
Text="{Binding Text}"
Visibility="Collapsed"
Style="{StaticResource UseCaseTextBox}"
LostFocus="textbox_LostFocus" />
</StackPanel>
</UserControl>
Decleration of dependency properties in codebehind:
https://github.com/Toudahl/SoftwareDesignHelper/blob/master/Helper/UserControls/DisplayAndEditControl.xaml.cs
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
"Text",
typeof(string),
typeof(UseCasePropertyDisplay),
new PropertyMetadata(null));
public static readonly DependencyProperty LabelProperty = DependencyProperty.Register(
"Label",
typeof(string),
typeof(UseCasePropertyDisplay),
new PropertyMetadata(null));
public string Text
{
get { return (string)GetValue(TextProperty); }
set {SetValue(TextProperty, value);}
}
public string Label
{
get { return (string)GetValue(LabelProperty); }
set { SetValue(LabelProperty, value);}
}
This is how i implement it on in the view:
https://github.com/Toudahl/SoftwareDesignHelper/blob/master/Helper/ViewsAndViewModels/ViewUseCases.xaml
<uc:UseCasePropertyDisplay Label="Name" Text="{Binding SelectedUseCase.Name, Mode=TwoWay}" />
From reading very similar questions here, im guessing that it has something to do with the way i set the context. However, the solution that has been provided to people (setting the relative source to the ancestor), doesnt work for me. Since its not available on my platform.
I am not really sure where to go from here, as this is the first time i try to use usercontrols, and the first time i use dependency properties.
School doesnt start untill a few weeks, so i cant get a hold of my teacher for this.
Instead of setting the DataContext global, set the first ui element to the inherited DataContext:
DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
As you have written, you can not use FindAncestor so you can try using a name and reference to it:
<UserControl
x:Class="Helper.UserControls.UseCasePropertyDisplay"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Helper.UserControls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400"
x:Name="Root">
<StackPanel DataContext="{Binding ElementName=Root}"
Orientation="Horizontal"
Margin="260,0,0,0">
<TextBlock Text="{Binding Label}"
Style="{StaticResource UseCaseTextBlock}"
x:Name="textblock_label"/>
<TextBlock x:Name="textblock_propertyContent"
Text="{Binding Text}"
Style="{StaticResource UseCaseFrameWorkTextElement}"
DoubleTapped="textblock_DoubleTapped" />
<TextBox x:Name="textbox_propertyContent"
Text="{Binding Text}"
Visibility="Collapsed"
Style="{StaticResource UseCaseTextBox}"
LostFocus="textbox_LostFocus" />
</StackPanel>
</UserControl>
Related
I'm trying to use compiled bindings in UWP with a simple use case.
In order to make my XAML more readable easy to manage, I've extracted the XAML of a DataTemplate to a UserControl. So I transformed this
MainPage.xaml
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ListView ItemsSource="{x:Bind ViewModel.Items}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:ProjectItem">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{x:Bind Name, Mode=OneWay}" />
<TextBlock Text="{x:Bind Description, Mode=OneWay}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Page>
Into this
MainPage.xaml
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ListView ItemsSource="{x:Bind ViewModel.Items}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:ProjectItem">
<local:MyUserControl1 />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Page>
MyUserControl1.xaml
<UserControl
x:Class="App1.MyUserControl1"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{x:Bind Name}" />
<TextBlock Text="{x:Bind Description}" />
</StackPanel>
</UserControl>
The problem is that it doesn't even compile because x:Bind doesn't know the context.
How does x:Bind cover this use case?
I'd suggest create Dependency Property for ProjectItem on your MyUserControl1.xaml.cs
public static readonly DependencyProperty ProjectItemProperty =
DependencyProperty.Register(
nameof(ProjectItem),
typeof(ProjectItem),
typeof(MyUserControl1),
null);
public ProjectItem ProjectItem
{
get => (ProjectItem)GetValue(ProjectItemProperty);
set => SetValue(ProjectItemProperty, value);
}
Then on your XAML, bind the properties of your ProjectItem Dependency Property:
<StackPanel Orientation="Horizontal">
<TextBlock Text="{x:Bind ProjectItem.Name, Mode=OneWay}" />
<TextBlock Text="{x:Bind ProjectItem.Description, Mode=OneWay}" />
</StackPanel>
Then on your MainPage.xaml, pass on the 'ProjectItem' collection item.
<DataTemplate x:DataType="local:ProjectItem">
<local:MyUserControl1 ProjectItem="{x:Bind}"/>
</DataTemplate>
If you use this approach, you could (or rather need to) add a property to MyUserControl1.xaml.cs that casts the current DataContext to a ProjectItem and returns it:
public ProjectItem Item => DataContext as ProjectItem;
public MyUserControl1()
{
InitializeComponent();
DataContextChanged += (s, e) => Bindings.Update();
}
You then bind to this property in the XAML markup:
<StackPanel Orientation="Horizontal">
<TextBlock Text="{x:Bind Item.Name}" />
<TextBlock Text="{x:Bind Item.Description}" />
</StackPanel>
The other option would to use non-compiled {Bindings} or get rid of MyUserControl1 and revert to the inline DataTemplate.
This could be faster as the DataContext is casted only once when the Control is Loaded.
public ProjectItem ProjectItem { get; private set; }
public MyUserControl1()
{
InitializeComponent();
Loaded += (s, e) =>
{
ProjectItem = (ProjectItem)DataContext;
Bindings.Update();
};
}
Add this if DataContext change in MainPage:
DataContextChanged += (s, e) =>
{
ProjectItem = (ProjectItem)DataContext;
Bindings.Update();
};
Based on the answer given by #mm8.
<UserControl x:Class="WatermarkTextBox"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="30"
d:DesignWidth="250">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</UserControl.Resources>
<Border>
<Grid x:Name="grid">
<TextBlock Text="{Binding Watermark, FallbackValue=This prompt dissappears as you type...}"
Visibility="{Binding ElementName=txtUserEntry, Path=Text.IsEmpty, Converter={StaticResource BooleanToVisibilityConverter}}" />
<TextBox Name="txtUserEntry"
Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
</Border>
</UserControl>
The above code shows my WatermarkTextBox control. In the code behind file I have set the DataContext. I left out all the code for the DP's of the control.
public WatermarkTextBox()
{
InitializeComponent();
grid.DataContext = this;
}
I had to bind the DataContext to the grid because otherwise the Text properties of both the watermark and actual text wouldn't display. The problem now is that I can't set the Background of the Border outside of the Grid.
I tried the code below but then only the Background of the Border is set and not the watermark and actual text.
public WatermarkTextBox()
{
InitializeComponent();
this.DataContext = this;
grid.DataContext = this;
}
In a UserControl like this you should never exlicitly set the DataContext to this or anyting else, because the DataContext is usually set externally when you use the UserControl somewhere in your application. The externally applied DataContext is typically (part of) the application's view model.
You should instead change your internal bindings so that they use an explicit RelativeSource:
<TextBlock
Text="{Binding Path=Watermark,
RelativeSource={RelativeSource AncestorType=UserControl},
FallbackValue=This prompt dissappears as you type...}"
Visibility="{Binding ElementName=txtUserEntry,
Path=Text.IsEmpty,
Converter={StaticResource BooleanToVisibilityConverter}}" />
<TextBox
Name="txtUserEntry"
Text="{Binding Path=Text,
UpdateSourceTrigger=PropertyChanged,
RelativeSource={RelativeSource AncestorType=UserControl}}" />
and then remove any DataContext assignment from the UserControl's constructor.
See e.g. this answer (and many other similar) that discuss this topic in detail.
In WPF it was a bit more confusing how to bind colors, like background color to a viewmodel property.
Are there other ways to bind Colors in Avalonia ?
Or is this example a good way ?
Avalonia View
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Button.Views.MainWindow"
Title="Button" Width="700">
<StackPanel Grid.Column="2" Orientation="Vertical" Gap="8" Margin="10">
<TextBox Name="Textbox3" Text="{Binding Textbox3Text}" Foreground="{Binding Textbox3Foreground}"/>
</StackPanel>
</Window>
Avalonia ViewModel
public class MainWindowViewModel
{
private IBrush _textbox3Foreground;
public IBrush Textbox3Foreground
{
get { return _textbox3Foreground; }
set
{
this.RaiseAndSetIfChanged(ref _textbox3Foreground, value);
}
}
public MainWindowViewModel()
{
Textbox3Foreground = Brushes.DarkOliveGreen;
}
}
Make sure that you have set the DataContext of the window to an instance of your view model class:
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Button.Views.MainWindow"
Title="Button" Width="700">
<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<StackPanel Grid.Column="2" Orientation="Vertical" Gap="8" Margin="10">
<TextBox Name="Textbox3" Text="{Binding Textbox3Text}" Foreground="{Binding Textbox3Foreground}"/>
</StackPanel>
</Window>
In general you don't usually define UI related things such as colours in the view model though. These kind of things are usually defined directly in the view without any bindings. But you can certainly bind to a Brush property like this.
I have a Problem with the ComboBox at wpf and xaml. The ItemsSource of my combobox is a list of (CollarTypesImage).
the binding is work fine but the problem when editing data, i can't select the item of my ComboBox.. maybe its selected but the image is not view...
but when click ComboBox, i can see all itams:
http://www.ahmadabouhamdh.com/tmp_global/1.png
i used RelativeSource , nothing changed, ComboBox not selection the my saved item:
<UserControl x:Class="TailorManager.Views.OrderDetailItem"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:vm="clr-namespace:TailorManager.ViewModels"
xmlns:Converter="clr-namespace:TailorManager.Converters"
mc:Ignorable="d"
d:DesignHeight="730" d:DesignWidth="556" FlowDirection="RightToLeft" >
<UserControl.Resources>
<!--<vm:OrderDetailItemViewModel x:Key="OrderDetailItemViewModel1" />-->
<Converter:ImageConverter x:Key="ImgConverter" />
</UserControl.Resources>
<Grid >
<ScrollViewer VerticalScrollBarVisibility="Auto" >
<ItemsControl>
<StackPanel>
<GroupBox Header="تفاصيل الياقة" Margin="5,5,5,0" VerticalAlignment="Top" Height="170">
<Grid>
<ComboBox ItemsSource="{Binding Path= DataContext.ImagesCollarTypes,
RelativeSource={RelativeSource AncestorType=UserControl,AncestorLevel=1}}"
SelectedValue="{Binding Path=OrderDetailItem.CollarTypesImage,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
SelectedValuePath="{Binding Path=OrderDetailItem.CollarTypesImage}"
Margin="393,106,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" Width="132" Height="38">
<ComboBox.ItemTemplate>
<DataTemplate>
<Image Width="50" Height="50" Source="{Binding Path= CollarImage,Converter={StaticResource ImgConverter} }" />
</DataTemplate>
</ComboBox.ItemTemplate >
</ComboBox>
</Grid>
</GroupBox>
<Grid/>
</StackPanel>
</ItemsControl>
</ScrollViewer>
</Grid>
</UserControl>
i added
SelectedItem="{Binding Path=OrderDetailItem.CollarTypesImage}"
and nothing changed.
i use this Control inside window has a different DataContext type,i set the value of (DataContext OrderDetailItem) from constructor of this control.
image below explain the binding is working fine:
this image when click edit to show my saved image from DB, my item not selected:
http://www.ahmadabouhamdh.com/tmp_global/2.png
here all the code:
public List<CollarTypesImage> ImagesCollarTypes
{
get
{
//ImagesCollarTypes[0].CollarImage
if (_imagesCollarTypes.Count == 0)
{
TailorManagerDBEntities db = new TailorManagerDBEntities();
_imagesCollarTypes = db.CollarTypesImages.ToList();
}
return _imagesCollarTypes;
}
set
{
_imagesCollarTypes = value;
RaisePropertyChanged(() => ImagesCollarTypes);
}
}
public partial class CollarTypesImage
{
public CollarTypesImage()
{
this.OrderDetails = new HashSet<OrderDetail>();
}
public System.Guid CollarTypeId { get; set; }
public byte[] CollarImage { get; set; }
public virtual ICollection<OrderDetail> OrderDetails { get; set; }
}
here the xaml code from window i used my control:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:TailorManager.ViewModels"
xmlns:util="clr-namespace:TailorManagerLib.Business;assembly=TailorManagerLib"
xmlns:local="clr-namespace:TailorManager.Views"
x:Class="TailorManager.Views.AddOrder"
Title="AddCustomer" Height="665" Width="974" MinWidth="600" MinHeight="666" FlowDirection="RightToLeft" >
<Window.Resources>
<vm:ManageOrderDetilsViewModel x:Key="ManageOrderDetilsViewModel1" />
</Window.Resources>
<Grid DataContext="{StaticResource ManageOrderDetilsViewModel1}" x:Name="GridDataContaner">
<Grid.Background>
...
</Grid.Background>
<GroupBox Header="تفاصيل الطلب" Margin="10,160,10,0" FlowDirection="RightToLeft">
<Grid Grid.Column="0" Name="GridOrderDetails">
<Grid.ColumnDefinitions>
<ColumnDefinition Name="ColumnDefinitionListDetails" Width="183*"/>
<ColumnDefinition Name="ColumnDefinitionDetails" Width="0*"/>
</Grid.ColumnDefinitions>
<Grid Margin="0,0,0,40" >
...
</Grid>
<Grid Grid.Column="1">
<Border BorderBrush="Black" BorderThickness="2" CornerRadius="3" Margin="4" >
<Grid>
<local:OrderDetailItem x:Name="OrderDetailItemControl" VerticalAlignment="Top" />
</Grid>
</Border>
</Grid>
...
</Grid>
</GroupBox>
</Grid>
</Window>
how i set the DataContext of the Control, this inside the command in VM of my window:
OrderDetailItemViewModel OrdDetailItem = new OrderDetailItemViewModel(Ord.OrderDetailsId);
OrderDetailItemControl.DataContext = OrdDetailItem;
Please how to fix it??
UPDATE
when i change the relative source as below:
<ComboBox Name="CmbBxImgCollarTyp" ItemsSource="{Binding Path= DataContext.ImagesCollarTypes, RelativeSource={
RelativeSource AncestorType={x:Type vm:OrderDetailItemViewModel}}"
SelectedValue="{Binding Path=OrderDetailItem.CollarTypesImage, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" SelectedValuePath="{Binding Path= OrderDetailItem.CollarTypesImage}" Margin="393,106,0,0" VerticalAlignment="Top"
HorizontalAlignment="Left" Width="132" Height="38">
<ComboBox.ItemTemplate>
<DataTemplate>
<Image Width="50" Height="50" Source="{Binding Path=CollarImage,
Converter={StaticResource ImgConverter}}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
the binding never work at all modes!, i change it to this way cause the datacontext of this control is an object of the viewmodel "OrderDetailItemViewModel"
What should be fix؟؟
You have an error in your RelativeSource Binding Path. You have used the type of UserControl, but the UserControl class does not have a property named ImagesCollarTypes... instead, you should use your UserControl where you defined the property... I'm assuming that class was named OrderDetailItem:
<ComboBox ItemsSource="{Binding Path= DataContext.ImagesCollarTypes, RelativeSource={
RelativeSource AncestorType={x:Type YourViewsPrefix:OrderDetailItem}}}"
SelectedValue="{Binding Path=CollarTypesImage, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" SelectedValuePath="{Binding Path=
CollarTypesImage}" Margin="393,106,0,0" VerticalAlignment="Top"
HorizontalAlignment="Left" Width="132" Height="38">
<ComboBox.ItemTemplate>
<DataTemplate>
<Image Width="50" Height="50" Source="{Binding Path=CollarImage,
Converter={StaticResource ImgConverter}}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
You should have received an error in the Output Window in Visual Studio saying something like Error: property 'ImagesCollarTypes' not found on object 'UserControl' or something similar.
Disclaimer: I didn't go through all of your code because you simply have too much there, so even after you fix this error, your code may still have other errors and not work as expected.
UPDATE >>>
For this Binding to work, the following assumptions were made:
The UserControl.DataContext must have a valid instance of an object set.
The object set as the UserControl.DataContext must have a public property named ImagesCollarTypes.
The ImagesCollarTypes property must be of a type that contains a public property named CollarTypesImage.
after check the Output window, i notes this error:
System.Windows.Data Error: 4 : Cannot find source for binding with
reference 'RelativeSource FindAncestor, AncestorType='Projectname.ViewModels.ViewModel', AncestorLevel='1''. BindingExpression:Path=LookupItems; DataItem=null; target element is 'ComboBox' (Name=''); target property is 'ItemsSource' (type 'IEnumerable')
then i change the RelativeSource from AncestorType from my ViewModel to UserControl, just like this:
RelativeSource={ AncestorType={x:Type UserControl},AncestorLevel=1}}"
and now everything working fine,
Thanks for members make an effort
I just started working with WPF and I'm trying to wrap my head around the XAML Bindings.
After a lot of reading I thought I had an easy enough usecase to test my knowledge. But nada :-( I can't figure it out.
What I'm trying to do is the following:
I have Address-Objects:
public IEnumerable<Address> Addresses
{
get
{
if (addresses == null)
{
addresses = new Repository<Address>().GetAll().ToList<Address>();
}
return addresses;
}
}
which have Rental-Objects e.g.
address.Rentals
also as IList.
On my MainWidow I want to have 2 UserControls, one for the address and one for the rental information. If I click the Navigator on the address user control, I only want to see the rental records of the current address.
MainWindow
<Window x:Class="Swopt.Mira.WPFApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
xmlns:local="clr-namespace:Swopt.Mira.WPFApp"
Title="MainWindow" Height="500" Width="525">
<Window.Resources>
<sampleData:DataContext x:Key="testDataContext" />
</Window.Resources>
<Grid x:Name="rootGrid" Background="White" DataContext="{StaticResource testDataContext}">
<StackPanel>
<local:RentalCustomer x:Name="rentalCustomer" Height="100" />
<local:Rentals Height="100" />
</StackPanel>
</Grid>
Address
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation" x:Class="Swopt.Mira.WPFApp.RentalCustomer"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
x:Name="RentalCustomerUserControl">
<Grid x:Name="rootGrid" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<StackPanel>
<TextBlock Text="Firma1"/>
<TextBox x:Name="Firma1" Text="{Binding ElementName=collectionNavigator, Path=CurrentItem.Firma1}" />
</StackPanel>
<telerik:RadCollectionNavigator Grid.Row="1"
Height="30"
Margin="2"
Grid.ColumnSpan="2"
x:Name="collectionNavigator"
Source="{Binding Addresses}"
/>
</Grid>
Rentals
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation" x:Class="Swopt.Mira.WPFApp.Rentals"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
x:Name="RentalsUserControl">
<Grid x:Name="rootGrid" Background="White" >
<StackPanel>
<TextBlock Text="VertragsNr"/>
<TextBox x:Name="VertragsNr" Text="{Binding ElementName=collectionNavigator2, Path=CurrentItem.VertragsNr}" />
</StackPanel>
<telerik:RadCollectionNavigator Grid.Row="1"
Height="30"
Margin="2"
x:Name="collectionNavigator2"
Source="{Binding Rentals}" />
</Grid>
Essentially what I want to do is Bind the DataContext of UserControl2 (Rentals) to the CurrentItem of collectionNavigator in UserControl1 (Addresses)
But I can't figure out how. I tried many things, with Binding Path and RelativeSource but none seem to work. the only way I could get it to work was to copy the content of UserControl1 into my MainWindow.xaml, but then I can't reuse it.
Any help is much appreciated.
UPDATE >>>>>
Working solution from Sheridan.
MainWindows
...
<local:RentalCustomer x:Name="rentalCustomer" Height="400" />
<local:Rentals Height="100" DataContext="{Binding CurrentAddress, ElementName=rentalCustomer}" />
RentalCustomer.xaml
...
<telerik:RadCollectionNavigator Grid.Row="1"
Height="30"
Margin="2"
Grid.ColumnSpan="2"
x:Name="collectionNavigator"
Source="{Binding Addresses}"
CurrentItem="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=CurrentAddress, Mode=OneWayToSource}"
/>
RentalCustomer.xaml.cs
public Address CurrentAddress
{
get { return (Address)GetValue(CurrentAddressProperty); }
set { SetValue(CurrentAddressProperty, value); }
}
// Using a DependencyProperty as the backing store for CurrentAddress. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CurrentAddressProperty =
DependencyProperty.Register("CurrentAddress", typeof(Address), typeof(RentalCustomer), new PropertyMetadata(null));
You can data bind the current item of a collection using the "/" Binding notation. Try something like this:
<UserControl Name="Control1" DataContext="{Binding SomeCollection}" />
<UserControl Name="Control2" DataContext="{Binding SomeCollection/}" />
Binding SomeCollection/ means bind to the current item of the SomeCollection collection. To make this work, you may need to set the Selector.IsSynchronizedWithCurrentItem Property to True on any container controls that you are selecting the current item in:
<ListBox ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True" ... />
UPDATE >>>
Without an IsSynchronizedWithCurrentItem property, the "/" Binding notation won't work. Instead, you could expose the selected item from the collection as a DependencyProperty on the relevant UserControl. Then you could do something like this:
<UserControl Name="Control2" DataContext="{Binding SelectedItem, ElementName=Control1}" />
You could provide the Rentals from your viewModel by binding the CurrentItem to your viewModel and expose the Rentals like this:
<telerik:RadCollectionNavigator CurrentItem={Binding CurrentItem} />
public Address CurrentItem
{
get; set;
}
public IEnumerable<Rentals> Rentals
{
get { return CurrentItem.Rentals; }
}