如何动态地使HierarchicalDataTemplate中的用户控件可编辑/只读?

时间:2015-01-13 17:59:32

标签: c# wpf mvvm hierarchicaldatatemplate

有没有人知道如何动态更改WPF HierarchicalDataTemplate中控件(TextBox,ComboBox等)的IsReadOnly属性?

我希望能够使HierarchicalDataTemplate中包含的控件对某些用户可编辑,对其他用户可以只读。

我已尝试将HierarchicalDataTemplate中每个控件上的IsReadOnly属性绑定到页面的ViewModel中的预定布尔值,但无法使绑定生效。任何帮助是极大的赞赏。

视图模型:

private bool _isReadOnlyBool;
public bool isReadOnlyBool
{
    get { return _isReadOnlyBool; }
    set
    {
        _isReadOnlyBool = value;
        RaiseChange("isReadOnlyBool");
    }
}

这里我展示了一个包含HierarchicalDataTemplate的TreeView控件。请注意,我尝试将HierarchicalDataTemplate中TextBox的IsReadOnly值绑定到Boolean" isReadOnlyBool"来自页面的ViewModel的值。

查看:

<TreeView HorizontalAlignment="Center" x:Name="treeView1" VerticalAlignment="Top" ItemsSource="{Binding Path=rsParentChild}"  Background="Transparent" BorderThickness="0" BorderBrush="Transparent" >
<TreeView.ItemContainerStyle>
    <Style>
        <Setter Property="TreeViewItem.IsExpanded" Value="True"/>
    </Style>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate>
    <HierarchicalDataTemplate ItemsSource="{Binding Path=rsParentChild, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
        <Grid Focusable="False" Margin="5,10,5,10">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1*"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Label Content="Action Text" FontSize="8" Grid.Row="0" Grid.Column="0"/>
            <TextBox Grid.Row="1" Grid.Column="0" 
             IsReadOnly="{Binding isReadOnlyBool, RelativeSource={RelativeSource AncestorType={x:Type Page}}}" 
             Background="#99FFFFFF" 
             BorderBrush="Black" 
             Text="{Binding Path=actionText, Mode=TwoWay}" 
             TextWrapping="Wrap" Margin="0,0,0,0" 
             LostFocus="TextBox_LostFocus" 
            />
        </Grid>
    </HierarchicalDataTemplate>
</TreeView.ItemTemplate>

我收到以下绑定错误:

System.Windows.Data错误:40:BindingExpression路径错误:&#39; isReadOnlyBool&#39;财产没有 发现在&#39;对象&#39; &#39;&#39;动作&#39; (名称=&#39;&#39;)&#39 ;. BindingExpression:路径= isReadOnlyBool; 的DataItem =&#39;动作&#39; (名称=&#39;&#39);目标元素是&#39; TextBox&#39; (名称=&#39;&#39);目标财产是'IsReadOnly&#39; (键入&#39;布尔&#39;)

1 个答案:

答案 0 :(得分:2)

您的模型/视图模型是如何构建的?我有类似的问题,但我只是使用文本块,但有些需要加粗,有不同的背景颜色等,所以动态绑定它们是必要的。我将我的代码修改为类似于你需要的代码,添加了TextBoxes而不是TextBlocks,并且我能够使IsReadOnly属性正常工作。这是我的TreeView的XAML,现在看起来已被修改。

    <TreeView x:Name="Tree" ItemsSource="{Binding Account}"  Margin="-2,45,-4,-18" BorderThickness="0,0,3,0" BorderBrush="{x:Null}" MouseDoubleClick="TreeViewItem_MouseDoubleClick_1">
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Account}" DataType="{x:Type local2:Accounts}">
                    <TextBox Text="{Binding Header}" IsReadOnly="{Binding IsReadOnly}" />
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
   </TreeView>

这就是我的模型的样子。

public class Accounts
{
    private readonly List<Accounts> accounts;
    public Accounts()
    {
        accounts = new List<Accounts>();
    }
    public bool IsNodeExpanded { get; set; }
    public string Header { get; set; }
    public Brush Foreground { get; set; }
    public Brush Background { get; set; }
    public FontWeight FontWeight { get; set; }
    public string Parent { get; set; }
    public bool IsReadOnly { get; set; }
    public List<Accounts> Account
    {
        get { return accounts; }
    }

}

你可以看到我已根据需要添加了属性,为了我的目的,我需要除了IsReadOnly之外的所有内容。我在TextBox中添加了它。我使用Accounts列表在我的ViewModel中创建了一个类似树的结构,这就是绑定到我的ItemsSource的内容。我会从ViewModel中获取代码,因为它非常难看,但我会发布一些可行的小样本。

        private List<Accounts> accounts;
        public List<Accounts> Account
        {
            get { return accounts; }
            set
            {
                accounts = value;
                NotifyPropertyChanged("Accounts");
            }
        }

        void SetTree()
        {
            Account.Add(new Accounts { Header = "Accounts", IsReadOnly = true });
            Account[0].Account.Add(new Accounts { Header = "Product Type", Foreground = fGround, FontWeight = FontWeights.Bold, IsReadOnly = true });
            SortedSet<string> uniqueProductType = GetUniqueItems("Product Type");
            Accounts tempAccount;
            for (int i = 0; i < uniqueProductType.Count(); i++)
            {
                tempAccount = new Accounts { Header = uniqueProductType.ElementAt(i), Foreground = fGround, FontWeight = FontWeights.Normal };
                accountsSystemNode.Add(uniqueProductType.ElementAt(i), tempAccount);
                tempAccount.Account.Add(new Accounts { Header = "Client Preferred Account Name", Foreground = fGround, FontWeight = FontWeights.Bold, IsReadOnly = true });
                Account[0].Account[0].Account.Add(tempAccount);
            }
        }

为了给这段代码提供一些上下文,我的树以标题“Accounts”开头,然后给出一组子类别。其中一个子类别是“产品类型”。帐户[0]是“帐户”,“帐户”的节点是帐户[0] [0],“产品类型”。然后我通过在我拥有的产品类型列表中循环来填充产品类型,创建一个新的Account对象并设置必要的值,并将其添加到我的“产品类型”节点。注意我没有为这些设置IsReadOnly值。这就是我验证它的工作原理。对于每个子类别标题,我将IsReadOnly属性设置为true并且无法编辑它们,而此子类别中的实际值IsReadOnly为false,并且我能够编辑这些值。

这就是这棵树的样子。我能够编辑这些文本框,但我无法编辑&#34;帐户&#34;或&#34;产品类型&#34;。

enter image description here