【问题标题】:UserControl Properties just working properly when they're strings用户控件属性在它们是字符串时才能正常工作
【发布时间】:2021-10-18 14:32:42
【问题描述】:

我正在尝试为 UWP 项目创建一个 UserControl,我希望在其中有一个用户正在使用的单元的指示器。

为了实现这一点,我创建了一个枚举并定义了控件将处理的单位类型,如下例所示:

 public static class UnitEnum
 {
    public enum Unit
    {
        Size,
        Weight,
        Currency,
        Percentage
    }
 }

然后,我在我的 UserControl 上创建了属性 ValueUnit,在将该控件添加到 UI 时应设置如下:

<usercontrols:NumericBox ValueUnit="Currency"/>
<usercontrols:NumericBox ValueUnit="Percentage"/>
<usercontrols:NumericBox ValueUnit="Size"/>
<usercontrols:NumericBox ValueUnit="Weight"/>

在 UserContol 内部,我有一个 switch case,其中指示符字符串发生变化以匹配该数据类型的系统默认单位(例如:货币 = €,大小 = M(来自米)),如下所示:

switch (ValueUnit)
{
        case Unit.Currency:
             UnitSymbol = System.Globalization.NumberFormatInfo.CurrentInfo.CurrencySymbol;
             break;
    
        case Unit.Percentage:
             UnitSymbol = "%";
             break;
        
        case Unit.Size:
             if (System.Globalization.RegionInfo.CurrentRegion.IsMetric) UnitSymbol = "m";
             break;
    
        case Unit.Weight:
             if (System.Globalization.RegionInfo.CurrentRegion.IsMetric) UnitSymbol = "Kg";
             break;
   }

然后我将UnitSymbol绑定到对应的TextBlock:

   <TextBlock Text="{x:Bind UnitSymbol}" VerticalAlignment="Center" Margin="5"/>

但在运行时,它总是显示与枚举的第一个值(在本例中为大小)相对应的符号,即使我已将 ValueUnit 设置为 XAML 中的任何其他值。

例子:

更新 1

我已经用ValueUnit == CurrencyUserControl 添加了一个名称,如下所示:

<usercontrols:NumericBox ValueUnit="Currency" x:Name="CurrencyBox"/>

在代码隐藏中,我添加了以下行并放置了一个断点:

    var a = CurrencyBox.ValueUnit;

当应用程序停止在那条线上a = SizeCurrencyBox.ValueUnit = Currency,两者都派生自Enums.UnitEnum.Unit,当推进执行时a也更改为Currency,但最后它仍然向我显示大小符号(米)。

更新 2

经过一些测试,我发现UserControl 中的任何其他属性都不起作用,只有获得Strings 的属性。

例子:

<usercontrols:NumericBox Header="Teste" ValueUnit="Currency" HasCalc="True" x:Name="CurrencyBox"/>
  • Header(即string)正在工作。 ✅
  • ValueUnit(这是我的UnitEnum 中的Unit)不起作用❌
  • HasCalc(这是正常的bool)不工作❌

UserControl 代码隐藏中的道具:

 public string Header { get; set; }
 public Unit ValueUnit { get; set; }
 public bool HasCalc { get; set; }

此外,属性UnitSymbol (string) 正在工作,因为其中的值已显示。

【问题讨论】:

  • 我认为ValueUnit="Currency" 无效。 ValueUnit="Unit.Currency" 听起来更像。请记住,枚举是编译时常量的集合。通常是integer 编译时间常数。如果没有有效值,系统通常必须默认设置。
  • 我不确定您是否可以像在属性上那样直接设置枚举值。你是如何申报财产的?在WPF 中,您必须采取一些变通办法——也许 UWP 也是如此。
  • @fredrik public Unit ValueUnit { get; set; }
  • 尝试使用 WPF 中的{x:Static ..} 看看是否可行。
  • @Christopher 我不知道这是不是真的,因为 IntelliSense 在我引入值时会识别 XAML 上的值,但我会尝试一下。

标签: c# windows visual-studio xaml uwp


【解决方案1】:

ValueUnit="Currency" 将 ValueUnit 设置为字符串“Currency”,而不是UnitEnum 中的值。然后,当您在 switch 语句中时,没有任何匹配项并返回默认值 0。

要解决此问题,您可以更改 case 条件以使用 .ToString() 方法,如下所示:

case Unit.Currency.ToString():
       UnitSymbol = System.Globalization.NumberFormatInfo.CurrentInfo.CurrencySymbol;
             break;

【讨论】:

  • 他还可以将值解析为枚举,然后切换它 - 这将具有能够警告尚未处理的案例的附加价值。
  • @RobJarvis 感谢您的帮助,但是当我应用 .ToString() 方法时,VisualStudiu 告诉我该值不存在于枚举中。
  • 诚然,@fredrik,我的解决方案有点老套,忽略了最佳实践。这是一种解决方法,它可以带来更好、更强大的解决方案,例如您的解决方案。
  • 要应用他的解决方案,您还必须将属性更改为字符串 - 而不是枚举
  • 当我在 xaml 上调用 UserControl 时,为什么不能使用 strings 以外的其他属性,例如 bool&lt;usercontrols:NumericBox Header="Teste" ValueUnit="Currency" HasCalc="True" x:Name="CurrencyBox"/&gt;
【解决方案2】:

我可以使用您发布的代码重现您的问题。该问题可能与DataBinding 有关。 X:bind 的默认绑定模式是一次性的,这意味着一旦创建绑定就不会改变。

我更改的主要内容是使用 Binding 而不是 X:Bind。

例如在用户控件中:

    <StackPanel>
    <TextBlock x:Name="MyTextBlock" Text="{Binding UnitSymbol,Mode=OneWay}"/>
    <Button Content="{Binding Header,Mode=OneWay}" Visibility="{Binding HasCalc,Mode=OneWay}"/>
</StackPanel>

在代码隐藏中我有:

 public TestUserControl()
    {
        this.InitializeComponent();
        this.Loaded += TestUserControl_Loaded;
    }

    private void TestUserControl_Loaded(object sender, RoutedEventArgs e)
    {
        switch (ValueUnit)
        {
            case UnitEnum.Unit.Currency:
                UnitSymbol = System.Globalization.NumberFormatInfo.CurrentInfo.CurrencySymbol;
                break;

            case UnitEnum.Unit.Percentage:
                UnitSymbol = "%";
                break;

            case UnitEnum.Unit.Size:
                if (System.Globalization.RegionInfo.CurrentRegion.IsMetric) UnitSymbol = "m";
                break;

            case UnitEnum.Unit.Weight:
                if (System.Globalization.RegionInfo.CurrentRegion.IsMetric) UnitSymbol = "Kg";
                break;
        }
        this.DataContext = this;
    }

然后我像这样从 MainPage 调用它:

  <local:TestUserControl HasCalc="False" ValueUnit="Percentage" Header="Yes"/>

结果如下所示:

由于这是一个非常简单的测试,如果您还有疑问,请告诉我。

【讨论】:

  • 您好,谢谢您的回答,这里的问题是我在构造函数上实现了登录,而不是在Loaded()事件中。我只需要在显示单元的 TextBlock 上从 x:Bind 更改为 Binding 并将其设置为两种方式。
猜你喜欢
  • 1970-01-01
  • 2012-03-16
  • 2020-04-26
  • 2022-01-06
  • 1970-01-01
  • 2016-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多