я сделал что-то подобное в прошлом, вот что вы можете сделать:
- Создать ViewModel (например NodeViewModel), который представляет собой каждый из дерева узлов в случае, если у вас еще нет
- Вы можете создать и реализовать интерфейс в этом NodeViewModel, например, IValidate, который предоставляет свойство
bool IsValid {get;set;}
. (Убедитесь, что вы используете INotifyPropertyChanged
в свойстве ViewModel)
Создайте стиль для типа управления, который вы используете в своем представлении для своих узлов (например, Button), и создайте триггер стиля (много примеров в Интернете), который устанавливает узел фона на красный, когда IsValid ложно и применить его к контролю:
<HierarchicalDataTemplate DataType="{x:Type ViewModel:NodeViewModel}" ItemsSource="{Binding Children}">
<Button Style="{StaticResource MyNodeStyle}"
Content="{Binding Path=.}"
</HierarchicalDataTemplate>
на ваш слой бизнес-логики, или контейнер ViewModel создать метод, который проверяет все узлы деревьев рекурсивно и устанавливает IsValid свойство всем им или определить свое бизнес-правило в IsValid Get (сделать его доступным только для чтения). Когда это подтверждение произойдет, ваши узлы автоматически станут красными, если они недействительны в соответствии с вашими правилами.
Надеюсь, что это поможет, дайте мне знать, если у вас есть вопросы.
EDIT: Добавлены примеры образцов для иллюстрации решения. Мое бизнес-правило состояло в том, что любой узел, начинающийся с «p», является Valid (зеленый), независимо от того, является ли он родителем или нет, но вы получаете идею ..
public class TreeNodeViewModel : ViewModelBase<TreeNodeViewModel>
{
private string _NodeText;
private ObservableCollection<TreeNodeViewModel> _Children;
public TreeNodeViewModel()
{
Children = new ObservableCollection<TreeNodeViewModel>();
}
public string NodeText
{
get { return _NodeText; }
set
{
_NodeText = value;
NotifyPropertyChanged(m => m.NodeText);
NotifyPropertyChanged(m => m.IsValid);
}
}
public bool IsValid
{
get { return !string.IsNullOrEmpty(NodeText) && NodeText.ToLower().StartsWith("p"); }
}
public ObservableCollection<TreeNodeViewModel> Children
{
get { return _Children; }
set
{
_Children = value;
NotifyPropertyChanged(m => m.Children);
}
}
}
public class TreeViewModel : ViewModelBase<TreeViewModel>
{
private ObservableCollection<TreeNodeViewModel> _RootNodeContainer;
private TreeNodeViewModel _RootNode;
public TreeViewModel()
{
InitializeTree();
}
private void InitializeTree()
{
RootNodeContainer = new ObservableCollection<TreeNodeViewModel>();
RootNode = new TreeNodeViewModel() { NodeText = "R1" };
RootNodeContainer.Add(RootNode);
TreeNodeViewModel p1 = new TreeNodeViewModel() {NodeText = "P1"};
p1.Children.Add(new TreeNodeViewModel(){NodeText = "Child1"});
RootNode.Children.Add(p1);
TreeNodeViewModel p2 = new TreeNodeViewModel() {NodeText = "P2"};
p2.Children.Add(new TreeNodeViewModel() { NodeText = "Child1" });
RootNode.Children.Add(p2);
TreeNodeViewModel xx = new TreeNodeViewModel() {NodeText = "XX"};
xx.Children.Add(new TreeNodeViewModel() { NodeText = "Child3" });
RootNode.Children.Add(xx);
}
public TreeNodeViewModel RootNode
{
get { return _RootNode; }
set
{
_RootNode = value;
NotifyPropertyChanged(m => RootNode);
}
}
public ObservableCollection<TreeNodeViewModel> RootNodeContainer
{
get { return _RootNodeContainer; }
set
{
_RootNodeContainer = value;
NotifyPropertyChanged(m => RootNodeContainer);
}
}
}
<TreeView Name="GoldTree" ItemsSource="{Binding RootNodeContainer}"
Background="#FFF0EDD1">
<TreeView.Resources>
<ResourceDictionary>
<Style TargetType="Button" x:Key="MyNodeStyle">
<Style.Triggers>
<DataTrigger
Binding="{Binding Path=IsValid,UpdateSourceTrigger=PropertyChanged}"
Value="False">
<Setter Property="Border.Background" Value="Red" />
</DataTrigger>
<DataTrigger
Binding="{Binding Path=IsValid,UpdateSourceTrigger=PropertyChanged}"
Value="True">
<Setter Property="Border.Background" Value="GreenYellow" />
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="TreeViewItem">
<Setter Property="Margin" Value="0,0,0,0" />
<!-- Disable blue highlighting on selection-->
<Setter Property="Focusable" Value="false" />
</Style>
<HierarchicalDataTemplate DataType="{x:Type ViewModel:TreeNodeViewModel}"
ItemsSource="{Binding Children}">
<Button Style="{StaticResource MyNodeStyle}" Content="{Binding Path=NodeText}" />
</HierarchicalDataTemplate>
</ResourceDictionary>
</TreeView.Resources>
</TreeView>
Вот что вы получите:
Ограничение этого решения является то, что проверка происходит, когда свойство NodeText устанавливается для каждого узла, так что вы можете не знать, в тот момент, является ли узел имеет детей, поэтому я предпочел бы создать метод в TreeViewModel, чтобы установить флаг IsValid
для всех узлов в какой-то момент.
Пожалуйста, покажите нам, что вы пробовали, а затем на основе вашего кода мы можем вам помочь/показать вам сделанные вами ошибки. –
Я не знаком с триггером стиля/валидацией данных в wpf. Я не знаю, как это сделать ... –