Search code examples
c#.netwinui-3winuicommunity-toolkit-mvvm

How can i call a method to update the ui?


WaveForm.cs

public class WaveForm
{
    public double Amplitude
    {
        get;set;
    }

    public double Frequency
    {
        get;set;
    }

    public string Wave()
    {
        return (Amplitude * Frequency).ToString();
    } 

    public WaveForm()
    {
        Amplitude = 1;
        Frequency = 2;
    }
}

Channel.cs

public class Channel
{

    public string ChannelId
    {
        get;set;
    }

    public WaveForm WaveForm
    {
        get;set;
    }

    public Channel(string channelId)
    {
        ChannelId = channelId;
        WaveForm = new WaveForm();
    }
}

MainViewModel.cs

[ObservableProperty]
private ObservableCollection<Channel> _channelSource = new();
<TextBox
    Text="{x:Bind WaveForm.Amplitude, Mode=TwoWay}"
    TextWrapping="Wrap" />
<TextBox
    Text="{x:Bind WaveForm.Frequency, Mode=TwoWay}"
    TextWrapping="Wrap" />
<TextBlock
    Style="{StaticResource BodyTextBlockStyle}"
    Text="{x:Bind WaveForm.Wave(), Mode=OneWay}"
    TextWrapping="Wrap" />

I have multiple channels, that i want to display. Each channel should be editable. If i change either the frequency or amplitude of a channel the "Wave()" is not updating. How can i fix this?


Solution

  • You can use NotifyPropertyChangedFor attribute that comes with the CommunityToolkit.Mvvm package, which you are already using.

    using CommunityToolkit.Mvvm.ComponentModel;
    using System.Collections.ObjectModel;
    
    namespace WinUI3App1;
    
    public partial class WaveForm : ObservableObject
    {
        [ObservableProperty]
        [NotifyPropertyChangedFor(nameof(Wave))]
        private double _amplitude = 1;
    
        [ObservableProperty]
        [NotifyPropertyChangedFor(nameof(Wave))]
        private double _frequency = 2;
    
        public string Wave => (Amplitude * Frequency).ToString();
    }
    
    public partial class Channel : ObservableObject
    {
        [ObservableProperty]
        private string _channelId = string.Empty;
    
        [ObservableProperty]
        private WaveForm _waveForm = new();
    
        public Channel(string channelId)
        {
            ChannelId = channelId;
        }
    }
    
    public partial class MainViewModel : ObservableObject
    {
        [ObservableProperty]
        private ObservableCollection<Channel> _channelSource = new();
    
        public MainViewModel()
        {
            ChannelSource.Add(new Channel("1"));
            ChannelSource.Add(new Channel("2"));
            ChannelSource.Add(new Channel("3"));
        }
    }
    

    Then in XAML:

    <Window
        x:Class="WinUI3App1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:local="using:WinUI3App1"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Grid>
            <ItemsRepeater ItemsSource="{x:Bind ViewModel.ChannelSource}">
                <ItemsRepeater.ItemTemplate>
                    <DataTemplate x:DataType="local:Channel">
                        <StackPanel>
                            <TextBox
                                Text="{x:Bind WaveForm.Amplitude, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                TextWrapping="Wrap" />
                            <TextBox
                                Text="{x:Bind WaveForm.Frequency, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                TextWrapping="Wrap" />
                            <TextBlock
                                Style="{StaticResource BodyTextBlockStyle}"
                                Text="{x:Bind WaveForm.Wave, Mode=OneWay}"
                                TextWrapping="Wrap" />
                        </StackPanel>
                    </DataTemplate>
                </ItemsRepeater.ItemTemplate>
            </ItemsRepeater>
        </Grid>
    </Window>