【问题标题】:Button control template and DataTriggers按钮控件模板和 DataTriggers
【发布时间】:2016-07-20 22:08:03
【问题描述】:

在我正在处理的应用程序中,我有几个要监控的项目。每个项目都有几种状态(开、关、更改)。 状态保存在模型中,窗口的 DataContext 设置为它。 每个按钮 DataContext 都设置为 SortableBindingList 中的单个项目。 在 XAML 中,我为按钮和其中的 DataTrigerrs 创建了控制模板。 但是,有时 item 仅显示第一个按钮,有时仅显示前三个按钮(取决于我在 DataTrigger 中放置的内容)。 当我检查 Snoop 时,我看到所有三个按钮都设置了正确的 DataContext 并且没有绑定错误。 我希望每个按钮都根据“serverstate”属性的值显示它的内容,但这不会发生。 我做错了什么?

控制模板转到 Window.Resources:

<ControlTemplate  x:Key="buttonTemplate" TargetType="Button" >
            <Border BorderThickness="1"
                    BorderBrush="Gray"
                    Margin="2"
                    Width="40" Height="35" 
                    >
                <Border.Background>
                    <SolidColorBrush Color="Brown" />
                </Border.Background>
                <ContentPresenter  />
            </Border>

            <ControlTemplate.Triggers>
                <DataTrigger Binding="{Binding serverstate}"  Value="0">
                    <Setter Property="Content">
                        <Setter.Value>
                            <TextBlock Name="a1"  Text="OFF" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White" />
                        </Setter.Value>
                    </Setter>
                </DataTrigger>
                <DataTrigger Binding="{Binding serverstate}" Value="1">
                    <Setter Property="Content">
                        <Setter.Value>
                            <TextBlock Name="a2" Text="CHNG" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White" />
                        </Setter.Value>
                    </Setter>
                </DataTrigger>
                <DataTrigger Binding="{Binding serverstate}" Value="2">
                    <Setter Property="Content">
                        <Setter.Value>
                            <TextBlock Name="a3" Text="ON" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White" />
                        </Setter.Value>
                    </Setter>
                </DataTrigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>

按钮:

<Button Name="state1" 
        DataContext="{Binding ActiveServers[0]}"
        Template="{StaticResource buttonTemplate}"
        />

<Button Name="state2" 
        DataContext="{Binding ActiveServers[1]}"
        Template="{StaticResource buttonTemplate}"
        />

<Button Name="state3" 
        DataContext="{Binding ActiveServers[2]}"
        Template="{StaticResource buttonTemplate}"
        />

<Button Name="state4" 
        DataContext="{Binding ActiveServers[3]}"
       Template="{StaticResource buttonTemplate}"
        />

<Button Name="state5" 
        DataContext="{Binding ActiveServers[4]}"
        Template="{StaticResource buttonTemplate}"
        />

这是按钮在窗口中的显示方式:

注意按钮 4 和 5 如何完全忽略 datacontext 中的属性值。

型号:

public class Model : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public Model()
    {

    }

    private SortableBindingList<Server> _activeServers;
    public SortableBindingList<Server> ActiveServers
    {
        get {
            if (_activeServers == null)
            {
                _activeServers = new SortableBindingList<Server>();
            }

            return _activeServers; 
        }
        set
        {
            _activeServers = value;
            OnPropertyChanged("serverList");
        }
    }

    // Create the OnPropertyChanged method to raise the event 
    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
}

【问题讨论】:

  • 我可以建议在TextBlocks 中使用ValueConverter 而不是DataTrigger 作为Text 属性。
  • 你的前 3 个按钮正确显示意味着 ActiveServers 集合包含一些未知的 serverstate 值。
  • @AnjumSkhan 不,我的收藏一切都很好。然而,问题已被以下用户 bar222 成功解决!

标签: wpf binding controltemplate datatrigger


【解决方案1】:

尝试更改Content 属性,但不要创建新的TextBlock

 <ControlTemplate.Triggers>
            <DataTrigger Binding="{Binding serverstate}"  Value="0">
                <Setter Property="Content" Value="OFF"></Setter>
            </DataTrigger>
            <DataTrigger Binding="{Binding serverstate}" Value="1">
                <Setter Property="Content" Value="CHNG"></Setter>
            </DataTrigger>
            <DataTrigger Binding="{Binding serverstate}" Value="2">
                <Setter Property="Content" Value="ON"></Setter>
            </DataTrigger>
        </ControlTemplate.Triggers>

【讨论】:

  • 谢谢,但我不能使用特定控件的预定义实例。我需要在此模板中使用任何通用类型的内容。例如,它可以是图像、画布或其他布局(如网格或堆栈面板)。
【解决方案2】:

我认为问题在于,两个按钮不能使用相同的Content。因此,每种类型的Content 对于每个触发值都会出现一次。您可以使用ContentTemplate 来避免这种情况。 所以代码应该是这样的(其他DataTriggers 相同)。它允许您稍后将DataTemplates 更改为更复杂。

<DataTrigger Binding="{Binding serverstate}" Value="2">
    <Setter Property="ContentTemplate">
        <Setter.Value>
            <DataTemplate>
                <TextBlock Text="ON" VerticalAlignment="Center" 
                           HorizontalAlignment="Center" Foreground="White" />
            </DataTemplate>
        </Setter.Value>
    </Setter>   
</DataTrigger>

【讨论】:

  • 谢谢,问题解决了!! :) 但是,我不明白 ContentTemplate 和 Content 之间的区别?我还认为我只能将 DataTemplate 用于 ItemsControls,因为它们有多个项目实例。你能指出像我这样的初学者可以理解的任何资源吗?
  • Wpf Unleashed 是一本好书,msdn 和 codeproject 文章也不错。 c# and .net platform by andrew troelsen 是一本适合初学者的好书。您可以接受将问题标记为已解决的答案。
  • 是的 WPF Unleashed 是一本很棒的书。已接受您的答案,已解决。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多