【问题标题】:Silverlight - Changing button text color created dynamicallySilverlight - 更改动态创建的按钮文本颜色
【发布时间】:2013-01-17 16:28:34
【问题描述】:

我正在尝试使用 ViewModel 更改 Silverlight 表单上动态创建的按钮的按钮文本颜色。我面临的问题是,当我更改按钮文本的颜色时,所有按钮都会生效。由于按钮是动态创建的,因此我无法对其进行控制。

有人建议我在 Model 中写入 ForegroundColor 属性,然后附加到按钮上,我尝试了如您在代码中看到的那样,但无能为力。

您能否看到我正在做的事情并帮助我提出您的建议,因为我不确定,我做对了。

谢谢

型号

namespace Web.Models
{
  [DataContract(IsReference = true)]
  public class Sales
  {
    [DataMember]
    public int SalesId { get; set; }
    [DataMember]
    public int ShowOrder { get; set; }
    [DataMember]
    public bool Active { get; set; }
    [DataMember]
    public bool Regurgitate { get; set; }

    [DataMember]
    public int ForegroundColor { get; set; }

    public Sales(Salese result)
    {
        SalesId = result.SalesId;
        ShowOrder = result.ShowOrder;
        Active = result.Active;
        Regurgitate = result.Regurgitate;            

        if (SalesId == 12)
        {
            var bytes = System.BitConverter.GetBytes(ForegroundColor);
            Color btnColor = Color.FromArgb(bytes[3], bytes[2], bytes[1], bytes[0]);

            SolidColorBrush myBrush = new SolidColorBrush(btnColor);
        }
   }
}

}

视图模型

private Brush _foregroundColor = new SolidColorBrush(Colors.Black); 

public override void Loaded()
{
    OnMainOutcome();
}


public Brush ForegroundColor
{
   get { return _foregroundColor; }
   set
   {
       if (_foregroundColor == value) return;
       _foregroundColor = value;                

       OnPropertyChanged("ForegroundColor");
    }
 }

 private void OnMainOutcome()
 {
    var selectedSalesId = (int)OutcomeCommand.CommandParameter;
    CurrentSubOutcomes = GetCurrentSubOutcomes(selectedSalesId);

    foreach (var index in CurrentOutcomes)
    {
       if (index.OutcomeId == 12)        
          ForegroundColor = new SolidColorBrush(Colors.Red);
       else
          ForegroundColor = new SolidColorBrush(Colors.Black);
    }
 }

XAML 已编辑

 <controls:ChildWindow.Resources>
    <converters:NumericToColorConverter x:Key="NumericToColorConverter"/>
</controls:ChildWindow.Resources>

 <ListBox Grid.Row="1" Height="Auto" MinHeight="200" Width="160" Margin="2,2,2,2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ItemsSource="{Binding Path=CurrentOutcomes}" Background="{x:Null}" BorderBrush="{x:Null}">
      <ListBox.ItemTemplate>
          <DataTemplate>
               <Button Height="30" Width="150" HorizontalAlignment="Center" Content="{Binding Outcome}" CommandParameter="{Binding SalesOutcomeId }" Command="{Binding Source={StaticResource ViewModel}, Path=OutcomeCommand}" Foreground="{Binding Source={StaticResource ViewModel}, Converter={StaticResource NumericToColorConverter}, Path=ForegroundColor}" />
          </DataTemplate>
      </ListBox.ItemTemplate>
 </ListBox>

转换器类新

  using System;
  using System.Windows.Data;
  using System.Windows.Media;
  using System.Windows;

  namespace Converters
  {
      public class NumericToColorConverter : IValueConverter
      {
        static readonly SolidColorBrush RED_BRUSH = new SolidColorBrush(Colors.Red);
        static readonly SolidColorBrush BLUE_BRUSH = new SolidColorBrush(Colors.Blue);

        public object Convert(object value, Type targetType,
        object parameter, System.Globalization.CultureInfo culture)
        {
           //Int32 id = System.Convert.ToInt32(value);

           //LinearGradientBrush brush = new LinearGradientBrush();
           //brush.StartPoint = new Point(0, 1);
           //brush.EndPoint = new Point(0, 0);
           //brush.GradientStops.Add(new GradientStop()
           //{
           //    Color = Colors.White,
           //    Offset = 0
           //});
           //brush.GradientStops.Add(new GradientStop()
           //{            
           //    Color = Color.FromArgb(
           //        200,
           //        System.Convert.ToByte((id * 103) % 256),
           //        System.Convert.ToByte((id * 157) % 256),
           //        System.Convert.ToByte((id * 233) % 256)
           //    ),
           //    Offset = 1
           //});

           //return brush;
           var OutcomeId = (int)value;

           if (OutcomeId == 12)
           {
              return RED_BRUSH;
           }
           else
           {
              return BLUE_BRUSH;
           }
    }

    public object ConvertBack(object value, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

}

【问题讨论】:

    标签: c# silverlight xaml


    【解决方案1】:

    您将Foreground 绑定到StaticResource 上的一个值,因此所有按钮都将绑定到这个相同的值。

    您可以创建一个特定的“ButtonForegroundConverter”,也可以将 Brush 属性添加到项目级视图模型中,该视图模型还具有您已经绑定到按钮的 ContentOutcome 属性。然后按钮 xaml 将如下所示:

    <Button ...
            Content="{Binding Outcome}" 
            Foreground="{Binding OutcomeForegroundBrush}" 
            ...
            />
    

    如果您直接绑定到实体,那么添加这样的属性不是一个好主意,因此上面的示例假设您有一个中间视图模型或控制器,您可以在其中添加这样的属性。

    如果您选择使用转换器,它将如下所示:

    <Button ...
            Content="{Binding Outcome}" 
            Foreground="{Binding OutcomeId, Converter={StaticResource OutcomeToForegroundConverter}}" 
            ...
            />
    

    还有转换器:

    namespace MyConverters {
    
        public sealed class OutcomeToColorConverter : IValueConverter {
    
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
    
                // We must have a valid integer value, double check bindings
                if (value == null) {
                    throw new ArgumentNullException("value", 
                        "Please make sure the value is not null.");
                }
    
                var OutcomeId = (int)value;
    
                if (OutcomeId == XXX) { 
                    return RED_BRUSH; 
                }
                else {
                    return BLUE_BRUSH;
                }
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
                throw new NotImplementedException();
            }
    
            static readonly SolidColorBrush RED_BRUSH = new SolidColorBrush(Colors.Red);
    
            static readonly SolidColorBrush BLUE_BRUSH = new SolidColorBrush(Colors.Blue);
        }
    }
    

    记得声明资源:

    <myconverters:OutcomeToForegroundConverter x:Key="OutcomeToForegroundConverter" />
    

    【讨论】:

    • 非常感谢您的帮助。实际上,在发布此问题后,我尝试以相同的方式实现,但在转换器类中它在 (int)value 上给出错误,因为特定的演员表无效。这是为什么?我正在使用与您相似的代码更新上述源代码。请看一下并提出建议。
    • 嗯,int 不能从 null 转换。我必须修复绑定以便始终获得非空值,或者更改转换器以首先检查null。请检查该值是否正确绑定。提示:查看您的 OUTPUT 窗口中的文本,这些文本将指示任何具有更具体信息的绑定错误。
    • 我可以将我的模型对象(类)作为参数绑定到转换器并访问它的值吗?我无法将值传递给转换器并针对转换器进行评估,因为它无法识别我传递的参数。我几乎尝试了每个值来绑定,虽然我现在没有收到任何错误,但我无法在转换器类中进行评估。有什么建议么?另外,我可以调试转换器类,以便我可以看到实际传递的内容吗?
    • 当然可以调试Converter。通过单击要停止的位置在函数内放置一个断点,然后按 F9。然后再次运行以查看代码停在那里。也可以将对象作为参数传递,但是我认为如果您在转换器内部的断点处开始调试,并查看输出,您可能会发现绑定存在可以修复的问题。当您停在那里时,也请查看 locals 窗口中的值。 (以及 LOG 的输出窗口)
    • 感谢所有输入,我现在已经解决了这个问题。我所做的只是从按钮绑定中删除了Source={StaticResource ViewModel},之后效果很好,但我仍然不明白,它是如何产生影响的?
    【解决方案2】:

    您的列表框显示Sales 的列表,但每个项目都被模板化以将按钮前景绑定到 VM 中的单个属性。在 Sales 类中创建 MyBrush 属性并绑定到它。

    namespace Web.Models
    {
      [DataContract(IsReference = true)]
      public class Sales
      {
        [DataMember]
        public int SalesId { get; set; }
        [DataMember]
        public int ShowOrder { get; set; }
        [DataMember]
        public bool Active { get; set; }
        [DataMember]
        public bool Regurgitate { get; set; }
    
        [DataMember]
        public int ForegroundColor { get; set; }
    
        [DataMember]
        public SolidColorBrush MyBrush { get; set; }
    
        public Sales(Salese result)
        {
            SalesId = result.SalesId;
            ShowOrder = result.ShowOrder;
            Active = result.Active;
            Regurgitate = result.Regurgitate;            
    
            if (SalesId == 12)
            {
                var bytes = System.BitConverter.GetBytes(ForegroundColor);
                Color btnColor = Color.FromArgb(bytes[3], bytes[2], bytes[1], bytes[0]);
    
                MyBrush = new SolidColorBrush(btnColor);
    
            }
       }
    }
    

    <ListBox Grid.Row="1" Height="Auto" MinHeight="200" Width="160" Margin="2,2,2,2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ItemsSource="{Binding Path=CurrentOutcomes}" Background="{x:Null}" BorderBrush="{x:Null}">
          <ListBox.ItemTemplate>
              <DataTemplate>
                   <Button Height="30" Width="150" HorizontalAlignment="Center" Content="{Binding Outcome}" CommandParameter="{Binding SalesOutcomeId }" Command="{Binding Source={StaticResource ViewModel}, Path=OutcomeCommand}" Foreground="{Binding MyBrush}"  />
              </DataTemplate>
          </ListBox.ItemTemplate>
     </ListBox>
    

    【讨论】:

    • 感谢您的建议,我尝试了您的代码 sn-p,但没有任何反应,它没有调用 MyBrush 属性并给出错误“远程服务器返回错误:未找到。”。为什么会这样?
    • 但是当我评论这行` //[DataMember] //public SolidColorBrush MyBrush { get;放; }` 错误消失,没有任何反应,这意味着按钮文本保持不变。
    • 可能SolidColorBrush 有序列化问题。您可以尝试将颜色值存储为简单类型,并将IValueConverter 与绑定一起使用。
    猜你喜欢
    • 2019-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-19
    • 1970-01-01
    • 2017-04-10
    • 2011-03-14
    相关资源
    最近更新 更多