0

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

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);
    }
};

任何帮助将非常感激。

4

1 回答 1

0

好的,您在其中实现 INPCSomeItem而不是MultiStateSelectionGridState这样,当您切换状态时,您几乎需要创建一个新CurrentState对象,而不是像CurrentState.Background = "Blue";在代码隐藏中那样

你还需要切换

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

OnPropertyChanged(new PropertyChangedEventArgs("CurrentState"));

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

我通过执行以下操作对此进行了测试:

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();

ListBox拥有它ItemsSource就像Items从上面一样。

你可以在这里找到一个工作示例

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

边注

我不知道您在何处或何时真正知道要为控件设置什么颜色,因此无法建议如何将其移至 xaml。但是您应该考虑让这些来自 xaml

于 2013-04-26T13:51:50.907 回答