Closed pictos closed 10 months ago
@dr1rrb @francoistanguay is there a workaround for this? Or a suggestion on how we can provide a better experience where there are multiple feeds of data that need to be displayed in the same UI such as this scenario
Have you looked into Feed.Combine?
I tested the Feed.Combine
, and even though it's working fine (successfully combining the Two FeedsI am not able to bind the data on a
FeedView`
For this Feed
public IFeed<WeatherInfo> CurrentWeather =>
Feed.Async(WeatherService.GetCurrentWeather);
public IFeed<CounterValue> CurrentCount =>
Feed.Async(CounterService.CountOne);
This way
public IFeed<(WeatherInfo, CounterValue)> FeedCombined =>
Feed.Combine(CurrentWeather, CurrentCount);
Or this, using named Tuples
public IFeed<(WeatherInfo WeatherInfo, CounterValue CounterValue)> FeedCombined =>
Feed.Combine(CurrentWeather, CurrentCount);
I tried many things on the XAML, including
<mvux:FeedView Source="{Binding FeedCombined}"
x:Name="FeedViewWeather">
<DataTemplate>
<StackPanel>
<TextBlock Text="Feeds Combined" />
<TextBlock FontSize="28" DataContext="{Binding Data}" Text="{Binding WeatherInfo.Temperature}" />
<TextBlock FontSize="28" DataContext="{Binding Data}" Text="{Binding CounterValue.Value}" />
</StackPanel>
</DataTemplate>
</mvux:FeedView>
and
<mvux:FeedView Source="{Binding FeedCombined}"
x:Name="FeedViewWeather">
<DataTemplate>
<StackPanel>
<TextBlock Text="Feeds Combined" />
<TextBlock FontSize="28" DataContext="{Binding Data}" Text="{Binding Item1.Temperature}" />
<TextBlock FontSize="28" DataContext="{Binding Data}" Text="{Binding Item2Value}" />
</StackPanel>
</DataTemplate>
</mvux:FeedView>
No matter what I tried, I could not get the value of the CombinedFeed
to be displayed.
Then I saw a couple of Binding error messages.
I keep investigating, and it seems it's not possible (maybe some of you already knew this) that it's not possible to use Binding expressions with Tuples, and the object resulting from the Feed.Combine()
method is exactly that, a Tuple
.
cc'ing @dr1rrb, maybe he can provide some light 💡
Actually, I was able to do the bindings but used a third entity.
public IFeed<WeatherInfo> CurrentWeather =>
Feed.Async(WeatherService.GetCurrentWeather);
public IFeed<CounterValue> CurrentCount =>
Feed.Async(CounterService.CountOne);
public IFeed<DataCombined> FeedCombined =>
Feed.Combine(CurrentWeather, CurrentCount)
.Select(x => new DataCombined(x.Item1, x.Item2 ));
public record DataCombined(WeatherInfo Weather, CounterValue Counter);
And with this XAML
<mvux:FeedView Source="{Binding FeedCombined}"
x:Name="FeedViewWeather">
<DataTemplate>
<StackPanel>
<TextBlock Text="Feeds Combined" />
<TextBlock FontSize="28" DataContext="{Binding Data}" Text="{Binding Weather.Temperature}" />
<TextBlock FontSize="28" DataContext="{Binding Data}" Text="{Binding Counter.Value}" />
</StackPanel>
</DataTemplate>
</mvux:FeedView>
Is this the way to go? If so, I will look into adding this to the docs.
@dr1rrb Do we support Tuples in code gen as well as regular records or just records? If not, should we add it to the backlog?
I think here the issue is not about the code gen of mvux, but more the fact that names in tuples are only at compilation time, the actual type used Tuple<T1, T2>
has 2 properties Item1
and Item2
on which you should be able to data-bind.
About the original issue, the issue is that if you have :
public record MyEntity(string Id, string Name);
// Model
public IFeed<string> Name { get; }
public IFeed<MyEntity> Entity { get; }
If we try to somehow aggregate properties in the Data
we could have name conflicts (on Name
in my example) unless if we add a complete new layer (e.g. Data.Entity.Name
) ... which sounds verbose and somehow weird when you are using a FeedView Source={Binding Entity}
. (The Data
is already source a lot of headaches :/)
BUT
You can already access "outside" of your Data
: There is also a property named Parent
which gives you access to the DataContext
of the FeedView
itself, i.e. the BindableModel
.
So, based on your example, if you don't want to use Feed.Combine
(because it's acceptable for you to display partial data with only Route
for instance), you can write:
<FeedView Source="{Binding Route}">
<DataTemplate>
<map:mapControl PinsSource="{Binding Parent.FavoriteLocations}" RoutePoints="{Binding Data}" />
</DataTemplate>
</FeedView>
Feed.Combine
Parent
(which is the FeedView.DataContext
, i.e. your BindableModel
)
What would you like to be added:
I would like to expose more bindable properties inside
Data
or in the FeedView in order to make it more robust. Let me explain with code. Let's say that I've a map page and I want to provide pins and routes to this map, and I have 2 distinct services that will provide this information.So the code will look like something like...
and my Model, will be:
This way I can use the FeedView and have more than one property exposed and the extension part of the framework will handle all these async calls for me.
Today this is impossible since the FeedView just exposes one bindable property, that's
Data
. One solution is to merge bothPin
andPoint
values in a single Model and pass them to the control, but it's not great to have to separate them before using, it should be done on the framework side.Why is this needed:
This will allow more flexibility for mobile developers, where they can use more than one
reactive property
inside their control. I see this as a limitation for this kind of scenario.For which Platform:
Anything else we need to know?
In order to make that happen, we can use Attributes and SourceGenerator, that will create the extra properties inside the
Data
bindable property that can be referenced on the view.