WPF - ListBoxItem - 动态更改DataTemplate元素颜色

时间:2013-04-25 21:08:09

标签: wpf data-binding dynamic custom-controls listboxitem

有几篇关于类似任务的文章。然而,似乎没有一个足够接近我正在做的事情。我有一个自定义控件,其模板中有一个ListBox。我根据自己的喜好重新设计了ListBox的模板。选择项目后,我想更改颜色。这是我的问题似乎与其他大多数人不同的部分:我不知道是什么颜色。它是正在渲染的项目中的任何颜色。我在XAML中绑定了不同的颜色,但是当我设置新颜色时它不会重绘。我更改了项目中的默认颜色,以确保模板首先获取正确的值。那成功了。我尝试过的事情:绑定,让项目实现INotifyPropertyChanged,以及EventTrigger与Storyboard(我从未真正构建过,因为我的值不是静态资源)。我遗漏了一些非常基本的东西。我确定。以下是帮助代码摘录:

XAML:

<Setter Property="ItemTemplate">
    <Setter.Value>
        <DataTemplate>
            <Border BorderBrush="{Binding CurrentState.Border}" BorderThickness="1">
                <TextBlock Text="{Binding DisplayObject}" Foreground="{Binding CurrentState.Foreground}" Background="{Binding CurrentState.Background}" MinHeight="12" MinWidth="50" Padding="2" ToolTip="{Binding ToolTip}"/>
            </Border>
        </DataTemplate>
    </Setter.Value>
</Setter>

助手班:

public class MultiStateSelectionGridState
{
    public string Background { get; set; }
    public string Foreground { get; set; }
    public string Border { get; set; }
    public string Text { get; set; }

    public MultiStateSelectionGridState()
    {
        Background = "White";
        Foreground = "Black";
        Border = "Black";
        Text = String.Empty;
    }
};

public interface IMultiStateSelectionGridItem : INotifyPropertyChanged
{
    object DisplayObject { get; }
    object ToolTip { get; }
    object Value { get; }
    MultiStateSelectionGridState CurrentState { get; set; }
    void OnPropertyChanged(PropertyChangedEventArgs e);
};

我不知道我可以发布多少项目类,所以我最初不会这样做。看起来如下:

class SomeItem : IMultiStateSelectionGridItem
{
    public int SomeInt { get; set; }
    public string SomeString { get; set; }
    public string SomeOtherString { get; set; }

    public object DisplayObject
    {
        get { return SomeString + CurrentState.Text; }
    }

    public object ToolTip
    {
        get { return SomeOtherString; }
    }

    public object Value
    {
        get { return SomeInt; }
    }

    private MultiStateSelectionGridState m_currentState;

    public MultiStateSelectionGridState CurrentState 
    {
        get
        {
            return m_currentState;
        }

        set
        {
            m_currentState = value;
            //Notice that this was just test code and I tried CurrentState, Background, and what 
            //you see there now.
            OnPropertyChanged(new PropertyChangedEventArgs("CurrentState.Background"));
        }
    }

    public SomeItem()
    {
        SomeInt = 0;
        SomeString = String.Empty;
        SomeOtherString = String.Empty;
        CurrentState = new MultiStateSelectionGridState();
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, e);
    }
};

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

确定您在SomeItem而非MultiStateSelectionGridState中实施INPC,因此当您切换状态时,您需要创建一个新的CurrentState对象,而不是在代码中使用CurrentState.Background = "Blue"; -behind

您还需要切换

OnPropertyChanged(new PropertyChangedEventArgs("CurrentState.Background"));

OnPropertyChanged(new PropertyChangedEventArgs("CurrentState"));

现在,当您切换CurrentState变量时(选择项目时),它将传播到View,并相应地查询它的属性。

我通过做类似的事情测试了这个:

Items = new ObservableCollection<SomeItem> {
  new SomeItem {
    CurrentState = new MultiStateSelectionGridState()
  }
};

// Simulating a Selected State change
var tempTask = new Task
  (
  () => {
    Thread.Sleep(5000);
    Items[0].CurrentState = new MultiStateSelectionGridState {
      Background = "Green",
      Border = "Blue"
    };
  },
  TaskCreationOptions.LongRunning
  );
tempTask.Start();

ListBoxItemsSource作为Items从上方开始。

您可以找到此Here

的有效示例

如果您不想继续为状态更改重新创建CurrentState对象,请执行 MultiStateSelectionGridState实施INPC本身。

<强>侧面注意

我不知道你何时或何时知道要为控件设置什么颜色,所以不能建议如何将其移动到xaml。但你应该期待这些来自xaml