[Solved] How to bind nested ObservableCollections in Unity/C#
I'm learning NoesisGUI but I'm stuck with problem from subject. No matter what tried I it's simply not working. I tried based on these examples
And here how it looks in Unity (I know it's not preety, I'm trying to learn these things)
And Xaml
This is what I want to achieve (It's embedded inside other view)
- https://forums.xamarin.com/discussion/5 ... ta-binding
- https://social.technet.microsoft.com/wi ... ation.aspx
And here how it looks in Unity (I know it's not preety, I'm trying to learn these things)
Code: Select all
public class CraftingPresenter : MonoBehaviour {
private Page craftingView;
(Few commands etc. ...)
public ObservableCollection<RecipeEntry> CraftItemEntries { get; private set; }
private void Start() {
InitView();
InitObservables();
SetUI();
}
private void InitView() {
craftingView = (Page)Noesis.GUI.LoadXaml("Assets/Scripts/Views/CraftingView.xaml");
mainViewPresenter.CurrentMainViewState
.Where(state => state == MainViewStates.Crafting)
.Subscribe(_ => {
mainViewPresenter.MainContent.Content = craftingView;
})
.AddTo(this);
}
private void InitObservables() {
CraftItemEntries = new ObservableCollection<RecipeEntry>();
}
private void SetUI() {
var listView = (ListView)craftingView.FindName("RecipesList");
listView.DataContext = this;
var actions = (UniformGrid)craftingView.FindName("Actions");
actions.DataContext = this;
}
public void UpdateRecipesList(Dictionary<ItemTypes, int> selectedIngridients) {
var availableRecipes = recipesDatabase.FindMatchingRecipes(selectedIngridients);
CraftItemEntries.Clear();
foreach (var recipe in availableRecipes) {
var newRecipeEntry = new RecipeEntry();
foreach (var ingridient in recipe.Ingridients) {
var itemEntry = inventoryPresenter.FindItemEntry(ingridient.Key);
newRecipeEntry.Ingridients.Add(itemEntry);
}
foreach (var product in recipe.RecipeProducts) {
var currentProduct = itemEntriesFactory.CreateItemEntry(
product.Key,
product.Value
);
newRecipeEntry.Products.Add(currentProduct);
}
CraftItemEntries.Add(newRecipeEntry);
}
}
}
public class ItemEntry {
public ItemTypes ItemType { get; private set; }
public string Name { get; private set; }
public TextureSource Thumbnail { get; private set; }
public int ItemCount { get; private set; }
public string Description { get; private set; }
public ItemEntry(
ItemTypes itemType,
TextureSource itemTexture,
int itemCount,
string description
) {
ItemType = itemType;
Name = itemType.ToString();
Thumbnail = itemTexture;
ItemCount = itemCount;
Description = description;
}
}
public class ItemEntriesFactory {
(...)
public ItemEntry CreateItemEntry(ItemTypes itemType, int quantity) {
var itemFromDB = itemsDatabase.FindItemRow(itemType);
return new ItemEntry(
itemFromDB.PrimaryKey,
new TextureSource(itemFromDB.Thumbnail),
quantity,
itemFromDB.Description
);
}
}
Code: Select all
<ScrollViewer
DockPanel.Dock="Top"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Auto">
<ListView
Name="RecipesList"
ItemsSource="{Binding CraftItemEntries}"
SelectionMode="Multiple">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="1" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<ListView ItemsSource="{Binding Ingridients}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="1" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<Grid MinHeight="100">
<Image
MinWidth="50"
MinHeight="50"
Margin="5"
VerticalAlignment="Center"
Source="{Binding Thumbnail}" />
<TextBlock
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Text="{Binding ItemCount}" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ScrollViewer>
Last edited by tkaczz on 25 May 2018, 14:19, edited 1 time in total.
Re: How to bind nested ObservableCollections in Unity/C#
I made workaround by creating ObservableCollection for ingridients displayed on top, and second in middle that displays recipes. But question from topic title still exists.
Re: How to bind nested ObservableCollections in Unity/C#
With big help of Log Verbosity set to "Bindings", console printed very helpful message:
After changing Products -> Products { get; set; } everything worked
Code: Select all
[NOESIS] Type 'RecipeProducts' does not contain a property named 'Products'
[NOESIS] Binding failed: Path=Products, Source=RecipeProducts(''), Target=ListBox(''), TargetProperty=ItemsControl.ItemsSource
-
sfernandez
Site Admin
- Posts: 2984
- Joined:
Re: [Solved] How to bind nested ObservableCollections in Unity/C#
Nice to hear you made progress.
Just some tips...
1. You can set the DataContext once in the View root and it will be inherited down the tree of elements. You don't probably need to look for individual named elements and assign it every time (like you did with "RecipesList" and "Actions").
2. A ListView control provides its own ScrollViewer so you don't need to wrap it with another ScrollViewer.
3. If your list is not going to show several columns of information for each item (like in a DataGrid), you can use a ListBox for better performance.
4. The data items provided as ItemsSource in a list behave as DataContext for their corresponding visual item in the list. So bindings specified in the ItemTemplate should be available as properties of the data item, otherwise bindings won't resolve.
Just some tips...
1. You can set the DataContext once in the View root and it will be inherited down the tree of elements. You don't probably need to look for individual named elements and assign it every time (like you did with "RecipesList" and "Actions").
2. A ListView control provides its own ScrollViewer so you don't need to wrap it with another ScrollViewer.
3. If your list is not going to show several columns of information for each item (like in a DataGrid), you can use a ListBox for better performance.
4. The data items provided as ItemsSource in a list behave as DataContext for their corresponding visual item in the list. So bindings specified in the ItemTemplate should be available as properties of the data item, otherwise bindings won't resolve.
Re: [Solved] How to bind nested ObservableCollections in Unity/C#
I'm beginner in Unity and NoesisGUI, so I really appreaciate your tips, thank you.Nice to hear you made progress.
Just some tips...
1. You can set the DataContext once in the View root and it will be inherited down the tree of elements. You don't probably need to look for individual named elements and assign it every time (like you did with "RecipesList" and "Actions").
2. A ListView control provides its own ScrollViewer so you don't need to wrap it with another ScrollViewer.
3. If your list is not going to show several columns of information for each item (like in a DataGrid), you can use a ListBox for better performance.
4. The data items provided as ItemsSource in a list behave as DataContext for their corresponding visual item in the list. So bindings specified in the ItemTemplate should be available as properties of the data item, otherwise bindings won't resolve.
Who is online
Users browsing this forum: Ahrefs [Bot] and 9 guests