C
C#14mo ago
__dil__

❔ [Avalonia] Basic question regarding subclassing

Let's say I have some types like so:
public abstract class Foo {}

public class FooA: Foo {}

public class FooB: Foo
{
public string Name { get; }
public int age { get; }
}
public abstract class Foo {}

public class FooA: Foo {}

public class FooB: Foo
{
public string Name { get; }
public int age { get; }
}
I'd like to display a List<Foo> where FooAs and FooBs would be displayed completely differently. Just as a random example, FooA would simply display "This is a FooA" with a red background while FooB would display "This is a FooB with name '...' and age '...' " in a blue background. You get the idea. The way I envision this is that FooA and FooB would themselves define how they should be displayed. I would be really grateful if someone could break this down to me. Bonus points if there's a working example.
40 Replies
nohopestage
nohopestage14mo ago
You could create a DataTemplate for each type: https://docs.avaloniaui.net/docs/templates/data-templates
Data Templates | Avalonia UI
Many controls have a Content property, such as ContentControl.Content. Window inherits from ContentControl, so lets use that as an example. You're probably familiar with what happens when you put a control in the Window.Content property - the window displays the control:
__dil__
__dil__OP14mo ago
I'm really unfamiliar with all these concepts so please correct me if I'm wrong, but isn't this more of a workaround? I don't necessarily need to display the objects directly. Like I could define views or controls or whatever, it doesn't have to be exactly the data types I've written I just don't know how to wire this all up to be clear, I'm like 45 minutes into avalonia, I know basically nothing. The only UI experience I have is like React and Svelte Thanks for the help btw
nohopestage
nohopestage14mo ago
No, I don't it's a workaround. That's what data templates are for
Jimmacle
Jimmacle14mo ago
generally with frameworks like this the business and presentation details are kept separate in this example your data is your model or viewmodel, and then your view will bind to that and the view is where you specify how things should actually appear
nohopestage
nohopestage14mo ago
You could do that, but you'd still need to put the views in data templates
__dil__
__dil__OP14mo ago
Ok, so would I define one View per subclass in this case? I'm really having trouble understanding how to apply that knowledge to this specific example I mostly understand the model-viewmodel-view distinction conceptually but it's not clear to me how to apply it in this specific case
Jimmacle
Jimmacle14mo ago
for a collection afaik data templates are the way to go you can define them as part of your view and i think it will automatically select one to use based on the object type check what noho posted, i'm a bit rusty with xaml
__dil__
__dil__OP14mo ago
Alright, thanks to both of you @Jimmacle @nohopestage 😄 Someone also suggested this
In this instance, the simplest (but definitely not the only) way to do this would be to add a method to Foo, public Control Draw(). Each implementation would have to override this function and handle drawing all the details, so woops, still typing You would also define the XAML somewhere, so if you want a specific layout for FooA, you would need to make FooAControl. FooBControl would need some elements that you can Bind the properties to. In the Draw method of each, you would create and return a new instance of the control that's created and then bind the properties as necessary. Then, just append the Controls to whatever it is that's iterating the elements.
Does that make sense or...? because it sounds really different from what you're suggesting
Jimmacle
Jimmacle14mo ago
that is very different, that sounds like a very manual way of doing it compared to taking advantage of what's already there to help you
nohopestage
nohopestage14mo ago
^
__dil__
__dil__OP14mo ago
alright, makes sense
Jimmacle
Jimmacle14mo ago
in a perfect world the only code directly related to UI would be done in xaml with no code-behind besides writing custom controls, anyway
__dil__
__dil__OP14mo ago
so you're saying that I should push as much stuff as possible to XAML?
nohopestage
nohopestage14mo ago
There's nothing wrong with code-behind though, as long as it's related to the UI
Jimmacle
Jimmacle14mo ago
yeah, i try to minimize it regardless the main thing is not mixing your business logic with UI code
__dil__
__dil__OP14mo ago
That makes sense. In the other GUIs I worked with, I could basically do stuff like this directly in the markup (would be XAML in this case)
if thisType {
markup to display it this way...
markup...
} else if thatType {
markup to display it that way...
} else ...
if thisType {
markup to display it this way...
markup...
} else if thatType {
markup to display it that way...
} else ...
I don't think conditionals are allowed in XAML so this kind of changes things for me but I'll try data templates and see how things go
nohopestage
nohopestage14mo ago
You could do that with a custom DataTemplate class, but I'd just create two data templates in xaml
__dil__
__dil__OP14mo ago
Thanks again for all the help, I'll give it a shot 😄 Is there a way to define like smaller fragments of XAML? For example, what if my data template is very complex (lots of markup). Wouldn't that make the xaml files really difficult to read?
nohopestage
nohopestage14mo ago
Yeah, you can put the template in a ResourceDictionary I believe
nohopestage
nohopestage14mo ago
Resources | Avalonia UI
Often, styles and controls will need to share resources such as (but not limited to) brushes and colors. You can put such resources in the Resources dictionary which is available on every style and control and then refer to these resources elsewhere.
nohopestage
nohopestage14mo ago
Actually, I think you have to create a DataTemplates file and use DataTemplateInclude
__dil__
__dil__OP14mo ago
A DataTemplates file? 🤔
nohopestage
nohopestage14mo ago
Yeah, if you have the Avalonia extension installed it might be an option in the add file dialog. If not, here's what it should look like: https://github.com/AvaloniaUI/Avalonia/discussions/8426#discussioncomment-4627825
GitHub
How to share DataTemplate s across projects? · AvaloniaUI Avalonia ...
In WPF I can put the DataTemplates in ResourceDictionary and merge it in other application. But in Avalonia there are many limits: DataTemplates can't be put in ResourceDictionary without key. ...
__dil__
__dil__OP14mo ago
No description
__dil__
__dil__OP14mo ago
doesn't seem like it? 🤔
nohopestage
nohopestage14mo ago
Just create a new file then
__dil__
__dil__OP14mo ago
Just to back track for a sec, I read the section on DataTemplate, but I still did not really understand how I'm supposed to make that work
__dil__
__dil__OP14mo ago
For example, I tried this:
No description
__dil__
__dil__OP14mo ago
obviously this is not doing what I think it is
nohopestage
nohopestage14mo ago
You can only have a single DataTemplate in ItemsControl.ItemTemplate. You can put both in ItemsControl.Resources
__dil__
__dil__OP14mo ago
So, something like this?
<ItemsControl.Resources>
<DataTemplate x:DataType="{x:Type m:TodoItem}">
<CheckBox Margin="4"
IsChecked="{Binding IsChecked}"
Content="{Binding Description}"
Background="Blue"/>
</DataTemplate>
<DataTemplate x:DataType="{x:Type m:TodoItemDated}">
<CheckBox Margin="4"
IsChecked="{Binding IsChecked}"
Content="{Binding Description}"
Background="Red"/>
</DataTemplate>
</ItemsControl.Resources>
<ItemsControl.Resources>
<DataTemplate x:DataType="{x:Type m:TodoItem}">
<CheckBox Margin="4"
IsChecked="{Binding IsChecked}"
Content="{Binding Description}"
Background="Blue"/>
</DataTemplate>
<DataTemplate x:DataType="{x:Type m:TodoItemDated}">
<CheckBox Margin="4"
IsChecked="{Binding IsChecked}"
Content="{Binding Description}"
Background="Red"/>
</DataTemplate>
</ItemsControl.Resources>
how do I use these resources afterwards?
__dil__
__dil__OP14mo ago
No description
nohopestage
nohopestage14mo ago
They should apply automatically
__dil__
__dil__OP14mo ago
this is what I have currently, so again I must be doing something wrong I get this:
Avalonia: Unable to find suitable setter or adder for property Resources of type Avalonia.Base:Avalonia.StyledElement for argument Avalonia.Markup.Xaml:Avalonia.Markup.Xaml.Templates.DataTemplate, available setter parameter lists are:
Avalonia.Controls.IResourceDictionary
Avalonia: Unable to find suitable setter or adder for property Resources of type Avalonia.Base:Avalonia.StyledElement for argument Avalonia.Markup.Xaml:Avalonia.Markup.Xaml.Templates.DataTemplate, available setter parameter lists are:
Avalonia.Controls.IResourceDictionary
nohopestage
nohopestage14mo ago
You can remove ItemsControl.ItemTemplate. Other than that seems ok
__dil__
__dil__OP14mo ago
I removed it, same error it seems
nohopestage
nohopestage14mo ago
Sorry, it should be ItemsControl.DataTemplates instead of ItemsControl.Resources
__dil__
__dil__OP14mo ago
Oh yeah now it compiles! Thanks Hurray, everything works as intended. Thanks a lot.
Accord
Accord14mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server