Skip to content

Commit

Permalink
Add a bunch more ListItem viewmodel properties, namely tags (#192)
Browse files Browse the repository at this point in the history
Doesn't use all these everywhere, but starts plumbing them into ViewModel's so that @niels9001 can start using more things in more places. 

![image](https://github.com/user-attachments/assets/f1c7c0c4-c4b2-49a4-889f-2c2e5f595f63)

I didn't actually colorize the tags, because that requires a Brush, and I don't think I'm supposed to put brushes in the viewmodels

ref #73
  • Loading branch information
zadjii-msft authored Dec 9, 2024
1 parent 186d411 commit 8d8c8c6
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,70 @@ public partial class ListItemViewModel(IListItem model, TaskScheduler scheduler)

// Remember - "observable" properties from the model (via PropChanged)
// cannot be marked [ObservableProperty]
public ITag[] Tags { get; private set; } = [];
public List<TagViewModel> Tags { get; private set; } = [];

public bool HasTags => Tags.Length > 0;
public bool HasTags => Tags.Count > 0;

public string TextToSuggest { get; private set; } = string.Empty;

public string Section { get; private set; } = string.Empty;

public override void InitializeProperties()
{
base.InitializeProperties();

// TODO load tags here, details, suggested text, all that
var li = _listItemModel.Unsafe;
if (li == null)
{
return; // throw?
}

// TODO TagViewModel not ITag
Tags = li.Tags ?? [];
Tags = li.Tags?.Select(t =>
{
var vm = new TagViewModel(t, Scheduler);
vm.InitializeProperties();
return vm;
})
.ToList() ?? [];
TextToSuggest = li.TextToSuggest;
Section = li.Section ?? string.Empty;

UpdateProperty(nameof(HasTags));
UpdateProperty(nameof(Tags));
UpdateProperty(nameof(TextToSuggest));
UpdateProperty(nameof(Section));
}

protected override void FetchProperty(string propertyName)
{
base.FetchProperty(propertyName);

var model = this._listItemModel.Unsafe;
if (model == null)
{
return; // throw?
}

switch (propertyName)
{
case nameof(Tags):
Tags = model.Tags?.Select(t =>
{
var vm = new TagViewModel(t, Scheduler);
vm.InitializeProperties();
return vm;
})
.ToList() ?? [];
UpdateProperty(nameof(HasTags));
break;
case nameof(TextToSuggest):
this.TextToSuggest = model.TextToSuggest ?? string.Empty;
break;
case nameof(Section):
this.Section = model.Section ?? string.Empty;
break;
}

UpdateProperty(propertyName);
}
}
45 changes: 45 additions & 0 deletions src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/TagViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.CmdPal.Extensions;
using Microsoft.CmdPal.UI.ViewModels.Models;
using Windows.UI;

namespace Microsoft.CmdPal.UI.ViewModels;

public partial class TagViewModel(ITag _tag, TaskScheduler Scheduler) : ExtensionObjectViewModel
{
private readonly ExtensionObject<ITag> _tagModel = new(_tag);

// Remember - "observable" properties from the model (via PropChanged)
// cannot be marked [ObservableProperty]
public string Text { get; private set; } = string.Empty;

public string Tooltip { get; private set; } = string.Empty;

public Color Color { get; private set; }

// TODO Icon
public ExtensionObject<ICommand> Command { get; private set; } = new(null);

public override void InitializeProperties()
{
var model = _tagModel.Unsafe;
if (model == null)
{
return;
}

Command = new(model.Command);
Text = model.Text;
Color = model.Color;
Tooltip = model.ToolTip;

UpdateProperty(nameof(Text));
UpdateProperty(nameof(Color));
UpdateProperty(nameof(Tooltip));
}

protected void UpdateProperty(string propertyName) => Task.Factory.StartNew(() => { OnPropertyChanged(propertyName); }, CancellationToken.None, TaskCreationOptions.None, Scheduler);
}
35 changes: 32 additions & 3 deletions src/modules/cmdpal/Microsoft.CmdPal.UI/ExtViews/ListPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,35 @@
EmptyValue="Collapsed"
NotEmptyValue="Visible" />

<StackLayout
x:Name="HorizontalStackLayout"
Orientation="Horizontal"
Spacing="8" />

<DataTemplate x:Key="TagTemplate" x:DataType="viewmodels:TagViewModel">
<!-- TODO: Actually colorize the tags again -->
<Border
Padding="4,2,4,2"
VerticalAlignment="Center"
BorderBrush="{ThemeResource TextBoxBorderThemeBrush}"
BorderThickness="1"
CornerRadius="4">
<StackPanel Orientation="Horizontal">
<!-- -TODO: Icon
<ContentControl
Width="12"
Height="12"
Margin="0,0,4,0"
Content="{x:Bind IcoElement, Mode=OneWay}"
Visibility="{x:Bind HasIcon, Mode=OneWay}" /> -->
<TextBlock
VerticalAlignment="Center"
FontSize="12"
Text="{x:Bind Text, Mode=OneWay}" />
</StackPanel>
</Border>
</DataTemplate>

<!-- https://learn.microsoft.com/windows/apps/design/controls/itemsview#specify-the-look-of-the-items -->
<DataTemplate x:Key="ListItemViewModelTemplate" x:DataType="viewmodels:ListItemViewModel">

Expand Down Expand Up @@ -69,12 +98,12 @@
TextWrapping="NoWrap"
Visibility="{x:Bind Subtitle, Mode=OneWay, Converter={StaticResource StringVisibilityConverter}}" />
</StackPanel>
<!-- TODO: Add tags again -->
<!--<ItemsRepeater ItemTemplate="{StaticResource TagTemplate}"

<ItemsRepeater ItemTemplate="{StaticResource TagTemplate}"
ItemsSource="{x:Bind Tags}"
Grid.Column="2"
Visibility="{x:Bind HasTags}"
Layout="{StaticResource HorizontalStackLayout}" />-->
Layout="{StaticResource HorizontalStackLayout}" />
</Grid>
</ListViewItem>
</DataTemplate>
Expand Down

0 comments on commit 8d8c8c6

Please sign in to comment.