筹集的财产更改为ViewModel之外的财产

发布于 2025-01-24 05:12:54 字数 380 浏览 3 评论 0原文

使用MVVMCROSS,FWIW I具有一个ViewModel,其主要是为了轻松XAML绑定目的而创建的几个属性。例如:

public int HomeScore
{
   get { return Contest.Team[HomeID].Score; }
}

homescore绑定到XAML视图中的文本块。 比赛是一个单身班,其中包含一个由两个团队组成的词典团队,HomeID代表其中一个钥匙。该值是一类TeamStats,其中包含属性整数得分。 当前的困境 /挑战是当另一种方法更新分数时,该通知应该如何传递到ViewModel,然后将视图传递给显示屏中的更新分数。 我已经玩过MVVMCross SetProperty和Raisepropertychang,但无济于事。

Using MvvmCross, fwiw I have a ViewModel with several properties created primarily for ease XAML binding purposes. For example:

public int HomeScore
{
   get { return Contest.Team[HomeID].Score; }
}

HomeScore is bound to a TextBlock in the XAML view.
Contest is a singleton class that contains a dictionary Team of two teams, HomeID representing one of the Keys. The value is a class of TeamStats, that contains a property integer Score.
The current dilemma / challenge is when another method updates the Score, how should that notification get passed on to the ViewModel and subsequently the View to show the updated score in the display.
I've played around with the MvvmCross SetProperty and RaisePropertyChanged at various levels but all to no avail.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

谜泪 2025-01-31 05:12:54

如果团队的“得分”属性本身出版/提高了房地产,则需要倾听它,并且在任何更改后都需要换取“ HomeScore”的财产。

Contest.Team[HomeID].PropertyChanged += PropagateHomeScore;

private void PropagateHomeScore (object sender, PropertyChangedEventArgs args)    { 
   if (e.PropertyName == "Score") {
      RaisePropertyChanged (nameof(HomeScore))
    }
}

顺便说一句,如果您丢弃便利包装的“ HomeScore”,然后将属性路径直接放入XAML中,则无需做任何事情。

WPF将绑定完整的路径,包括自动化的更改侦听器。 Afaik可以处理字典索引器。

XAML

<TextBlock Text="{Binding Contest.Team[HomeID].Score}" />

(HOMEID可能应由其实际价值代替)。

**
更新:

演示,用于绑定静态类词典 **

xaml window1.xaml

<Window x:Class="WpfApp1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApp1"
    Title=""
    Width="700"
    Height="220">
    <StackPanel HorizontalAlignment="Center">
        <StackPanel.Resources>
            <Style x:Key="Style1" TargetType="Control">
                <Setter Property="FontSize" Value="20" />
                <Setter Property="FontWeight" Value="Bold" />
                <Setter Property="Padding" Value="20" />
                <Setter Property="VerticalAlignment" Value="Center" />
            </Style>
        </StackPanel.Resources>
        <Label Style="{StaticResource Style1}">Dictionary-Binding + INotifyPropertyChanged Demo</Label>

        <StackPanel HorizontalAlignment="Center"
            Orientation="Horizontal">

            <Button Margin="10"
                Click="ButtonBase_OnClick"
                Content="Increment:"
                Style="{StaticResource Style1}" />
            <TextBox Foreground="Magenta"
                IsReadOnly="True"
                Style="{StaticResource Style1}"
                Text="{Binding Source={x:Static local:Contest.Team}, Path=[1].Score, Mode=OneWay}" />

        </StackPanel>
    </StackPanel>
</Window>

cs:window1.xaml.cs
+ VM背后的代码

namespace WpfApp1 {

    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Windows;

    public partial class Window1 {
        public Window1() => InitializeComponent();
        private void ButtonBase_OnClick(object sender, RoutedEventArgs e) => Contest.Team[1].Score++;
    }
    public static class Contest {
        public static Dictionary<int, ScoreObject> Team { get; } = new() {
                                 { 1, new ScoreObject { Score = 10 } },
                                 { 2, new ScoreObject { Score = 20 } },
                                 { 3, new ScoreObject { Score = 30 } },
                                 { 4, new ScoreObject { Score = 40 } },
        };
    }
    public class ScoreObject : INotifyPropertyChanged {
        private int _score;
        public int Score {
            get => _score;
            set {
                if (_score != value) {
                    _score = value;
                    OnPropertyChanged(nameof(Score));
                }
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName) {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

If the Team's "Score" property itself publishes/raises PropertyChanged, you need to listen to it and on any change raise PropertyChanged for "HomeScore".

Contest.Team[HomeID].PropertyChanged += PropagateHomeScore;

private void PropagateHomeScore (object sender, PropertyChangedEventArgs args)    { 
   if (e.PropertyName == "Score") {
      RaisePropertyChanged (nameof(HomeScore))
    }
}

By the way, if you discard the convenience wrapper "HomeScore" and put the property path directly in XAML, you don't have to do anything.

WPF would bind the complete path including the change listeners automagically. Afaik it can handle the dictionary indexer.

XAML

<TextBlock Text="{Binding Contest.Team[HomeID].Score}" />

(HomeID should likely be replaced by its actual value).

**
Update:

Demo for Binding to a dictionary of a static class**

XAML Window1.xaml

<Window x:Class="WpfApp1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApp1"
    Title=""
    Width="700"
    Height="220">
    <StackPanel HorizontalAlignment="Center">
        <StackPanel.Resources>
            <Style x:Key="Style1" TargetType="Control">
                <Setter Property="FontSize" Value="20" />
                <Setter Property="FontWeight" Value="Bold" />
                <Setter Property="Padding" Value="20" />
                <Setter Property="VerticalAlignment" Value="Center" />
            </Style>
        </StackPanel.Resources>
        <Label Style="{StaticResource Style1}">Dictionary-Binding + INotifyPropertyChanged Demo</Label>

        <StackPanel HorizontalAlignment="Center"
            Orientation="Horizontal">

            <Button Margin="10"
                Click="ButtonBase_OnClick"
                Content="Increment:"
                Style="{StaticResource Style1}" />
            <TextBox Foreground="Magenta"
                IsReadOnly="True"
                Style="{StaticResource Style1}"
                Text="{Binding Source={x:Static local:Contest.Team}, Path=[1].Score, Mode=OneWay}" />

        </StackPanel>
    </StackPanel>
</Window>

CS: Window1.xaml.cs
Code behind + VM

namespace WpfApp1 {

    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Windows;

    public partial class Window1 {
        public Window1() => InitializeComponent();
        private void ButtonBase_OnClick(object sender, RoutedEventArgs e) => Contest.Team[1].Score++;
    }
    public static class Contest {
        public static Dictionary<int, ScoreObject> Team { get; } = new() {
                                 { 1, new ScoreObject { Score = 10 } },
                                 { 2, new ScoreObject { Score = 20 } },
                                 { 3, new ScoreObject { Score = 30 } },
                                 { 4, new ScoreObject { Score = 40 } },
        };
    }
    public class ScoreObject : INotifyPropertyChanged {
        private int _score;
        public int Score {
            get => _score;
            set {
                if (_score != value) {
                    _score = value;
                    OnPropertyChanged(nameof(Score));
                }
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName) {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文