A data binding question
Hi,
I have 2 UI(View): MyControl.Xaml, MainWindow.Xaml.
2 ViewModel: MyControlVM(has a string member: Title), MainWindowVM(has a string member: MainWindowTitle),
then how binding child View's DataContext? especially in UE4's blueprint
I have 2 UI(View): MyControl.Xaml, MainWindow.Xaml.
Code: Select all
<!-- MyUserControl -->
<UserControl>
<Grid>
<Label Content="{Binding Title}">
</Grid>
</UserControl>
Code: Select all
<!-- MainWindow -->
<UserControl>
<Grid>
<Label Content="{Binding MainWindowTitle}">
<local: MyUserControl <!-- How to binding its Title? -->>
</Grid>
</UserControl>
then how binding child View's DataContext? especially in UE4's blueprint
Re: A data binding question
Hi,
At the moment there's no way to set a DataContext for elements other than the root, via the SetDataContext function. This data context is inherited by all elements.
I was thinking about adding a SetDataContextForElement function to allow having different DataContexts in different elements of the tree, but it's still not implemented. I'll try to get it into the next code release. For now you can add MyControlVM as a property of MainWindowVM, and then change your xaml like this:
<local: MyUserControl DataContext="{Binding MyControlVM}">
I'll let you know once I've implemented SetDataContextForElement.
At the moment there's no way to set a DataContext for elements other than the root, via the SetDataContext function. This data context is inherited by all elements.
I was thinking about adding a SetDataContextForElement function to allow having different DataContexts in different elements of the tree, but it's still not implemented. I'll try to get it into the next code release. For now you can add MyControlVM as a property of MainWindowVM, and then change your xaml like this:
<local: MyUserControl DataContext="{Binding MyControlVM}">
I'll let you know once I've implemented SetDataContextForElement.
Re: A data binding question
Thank you.Hi,
At the moment there's no way to set a DataContext for elements other than the root, via the SetDataContext function. This data context is inherited by all elements.
I was thinking about adding a SetDataContextForElement function to allow having different DataContexts in different elements of the tree, but it's still not implemented. I'll try to get it into the next code release. For now you can add MyControlVM as a property of MainWindowVM, and then change your xaml like this:
<local: MyUserControl DataContext="{Binding MyControlVM}">
I'll let you know once I've implemented SetDataContextForElement.
And I need to hold a ref of UNoesisInstance in ViewModel, then I can bind events to the UNoesisInstance's element, I don't how to do this for MyUserControl. The blueprint function FindName return a BaseComponent(UObject), but I need a NoesisInstance. Or some other class(BlueprintType) will do the same thing?
Maybe in C++, I could hold the View by MyUserControl* MyControlParam = FindName<MyUserControl>("ControlInstanceName"), and set the return value to MyUserControlVM.
Re: A data binding question
Hi,
I've committed a new version to GitHub. I've added a new function called TrySetDataContext. You can use it in combination with FindName. You use FindName to get the element you want, then TrySetDataContext to set the data context. The Try in the name is because it takes an UObject as both parameters, but only works if the Element parameter is indeed a Noesis FrameworkElement.
Please, let us know if this solves your problem.
I've committed a new version to GitHub. I've added a new function called TrySetDataContext. You can use it in combination with FindName. You use FindName to get the element you want, then TrySetDataContext to set the data context. The Try in the name is because it takes an UObject as both parameters, but only works if the Element parameter is indeed a Noesis FrameworkElement.
Please, let us know if this solves your problem.
-
sfernandez
Site Admin
- Posts: 2984
- Joined:
Re: A data binding question
Another option is to provide MyControlVM as nested data of the parent MainWindowVM. That is, you store MyControlVM in a public property ("Content" for example) of the MainWindowVM. Then you can bind MyUserControl DataContext to that property:
Code: Select all
<!-- MainWindow -->
<UserControl>
<Grid>
<Label Content="{Binding MainWindowTitle}">
<local:MyUserControl DataContext="{Binding Content}"/>
</Grid>
</UserControl>
Re: A data binding question
Hi
2 methods all works
Is there some way could help me hold a View's ref in ViewModel? the C++ code may do it, but not flexible
for ItemsControl, I don't have a right way to set a ref to View automatically
2 methods all works
Is there some way could help me hold a View's ref in ViewModel? the C++ code may do it, but not flexible
Code: Select all
void UMainWindowViewModel::InitialzieDataBinding()
{
//MainWindow can hold a ref to UNoesisInstance(NGUI) easily
if (VirtualJoystickVM && NGUI && NGUI->Xaml)
{
VirtualJoystick* VJoystick = NGUI->Xaml->FindName<VirtualJoystick>(TCHAR_TO_UTF8( *JoystickControlName));
if (VJoystick)
{
//Let child hold View's ref
VirtualJoystickVM->SetViewRaw(VJoystick);
}
}
if (TouchButtonVM && NGUI && NGUI->Xaml)
{
GameGUI::TouchButton* TouchBtn = NGUI->Xaml->FindName < GameGUI::TouchButton > (TCHAR_TO_UTF8(*TouchButtonName));
if (TouchBtn)
{
TouchButtonVM->SetViewRaw(TouchBtn);
}
TouchButtonVM->OnDragStarted.AddDynamic(this, &UMainWindowViewModel::ProcessTouchButtonEvent);
}
}
Code: Select all
<ItemsControl ItemsSource="{Binding TouchButtonVMList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" <!-- Orientation doesn't work -->>
<local:TouchButton >
</local:TouchButton>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Re: A data binding question
Yous still have to use C++ for the VM, but what you can do is use FindName in the Blueprint, and have a native function in your VM class that takes an UObject*. In that function you can retrieve the Noesis component, like this:
Is this what you had in mind?
Code: Select all
void VirtualJoystickVM::SetView(UObject* WrappedView)
{
Noesis::Ptr<Noesis::BaseComponent> Component = NoesisCreateComponentForUObject(WrappedView);
if (Component)
{
VirtualJoystick* VJoystick = NsDynamicCast<VirtualJoystick*>(Component.GetPtr());
if (VJoystick)
{
SetViewRaw(VJoystick);
}
}
}
-
sfernandez
Site Admin
- Posts: 2984
- Joined:
Re: A data binding question
About this code, ItemTemplate property defines the appearance of a single item only.Code: Select all<ItemsControl ItemsSource="{Binding TouchButtonVMList}"> <ItemsControl.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal" <!-- Orientation doesn't work -->> <local:TouchButton /> </StackPanel> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl>
If you want to manage the layout of items in an ItemsControl, you should use the ItemsPanel property:
Code: Select all
<ItemsControl ItemsSource="{Binding TouchButtonVMList}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:TouchButton />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Re: A data binding question
Maybe late, but try this:
if your dataContext is some xaml file, then try this, similar is working on my side (but instead UserControl I use grid).
Btw. I think your labels missing "/" sign.
Code: Select all
<!-- MainWindow -->
<UserControl>
<Grid>
<Label x:Name="TitleElement" Content="{Binding MainWindowTitle}">
</Grid>
</UserControl>
Code: Select all
<!-- MyUserControl -->
<UserControl>
<Grid>
<Label Content="{Binding ElementName=TitleElement, Path=Content}">
</Grid>
</UserControl>
Code: Select all
<!-- MyUserControl -->
<UserControl>
<Grid>
<Label Content="{Binding ElementName=TitleElement, Path=DataContext.NameOfDataContext[MainWindowTitle]}"> // It depends which element you add DataContext. In this case I think you add DataContext in to label named TitleElement
</Grid>
</UserControl>
Code: Select all
<Label x:Name="TitleElement" Content="{Binding MainWindowTitle}" />
Re: A data binding question
so, I have to call SetView everytime add/remove a array element in DataContext?
the child elements is defined in a template, and initialized at runtime, I don't its name, the FindName may be helpless?
the child elements is defined in a template, and initialized at runtime, I don't its name, the FindName may be helpless?
Who is online
Users browsing this forum: No registered users and 66 guests