【问题标题】:WPF ItemsControl:- Changes Property of Items inside ItemControle after ItemSource Property of ItemsControl being changed at Run-TimeWPF ItemsControl:- 在运行时更改 ItemsControl 的 ItemSource 属性后,更改 ItemControle 内的项目属性
【发布时间】:2011-07-21 09:59:58
【问题描述】:

我有以下场景:

我用过一个ItemsControl

根据ItemsSource生成Button给它?

现在,

当我点击nextbutton时。[看看ma​​inwindow.xaml]。

ItemsControl(pageControl) 的 ItemsSource 变化

并且还必须更改buttonbackground,根据我的情况,其内容等于CurrentPage 属性。

假设,

第 1 步:在按钮的点击事件中首先我将更改ItemsSourceItemsControl

第 2 步:然后我会改变 特定按钮的Background 但不是在背景中发生变化,而是我得到以下错误。

This operation is valid only on elements that have this template applied.

注意:- 如果我直接更改Background 而不对ItemsSource 进行任何更改,我没有任何问题。

看看下面的代码。

Mainwindow.xaml

  <Window x:Class="CurrentPageProblem.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <Style TargetType="Button" x:Key="buttonStyle">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <Border  CornerRadius="2,2,2,2"  HorizontalAlignment="Center" x:Name="borderTemplate" Background="{TemplateBinding Background}">
                            <ContentPresenter/>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="true">
                                <Setter TargetName="borderTemplate"  Property="Border.BorderBrush" Value="Gray" />
                                <Setter TargetName="borderTemplate"  Property="Border.BorderThickness" Value="1" />
                            </Trigger>
                            <Trigger Property="IsPressed" Value="true">
                                <Setter TargetName="borderTemplate"  Property="Border.BorderBrush" Value="Lime" />
                            </Trigger>
                            <Trigger Property="IsFocused" Value="true">
                                <Setter TargetName="borderTemplate"  Property="Border.Background" Value="#FD7" />
                            </Trigger>
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter TargetName="borderTemplate"  Property="Border.Background" Value="LightGray"></Setter>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="47*" />
            <RowDefinition Height="264*" />
        </Grid.RowDefinitions>
        <ItemsControl Name="pageControl" ItemsSource="{Binding Path=PageCollection}" Grid.Row="0">
            <ItemsControl.Template>
                <ControlTemplate TargetType="ItemsControl">
                    <Border >
                        <StackPanel>
                            <ItemsPresenter></ItemsPresenter>
                        </StackPanel>
                    </Border>
                </ControlTemplate>
            </ItemsControl.Template>
            <ItemsControl.ItemsPanel x:Uid="pageItemTemplate">
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Horizontal"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Button x:Name="pageNumberButton" Margin="3,4" Style="{StaticResource buttonStyle}" Content="{Binding Path=Page_Number}"></Button>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

        <Button Content="Next" Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="136,98,0,0" Name="nextButton" VerticalAlignment="Top" Width="75" Click="button1_Click" />
    </Grid>
</Window>

Mainwindow.xaml.cs

  public partial class MainWindow : Window,INotifyPropertyChanged
        {
            ObservableCollection<PageNumber> pageCollection = new ObservableCollection<PageNumber>();
            public MainWindow()
            {
                InitializeComponent();

                pageCollection.Add(new PageNumber("  0  "));
                pageCollection.Add(new PageNumber("  1  "));
                pageCollection.Add(new PageNumber("  2  "));
                pageCollection.Add(new PageNumber("  3  "));
                pageCollection.Add(new PageNumber("  4  "));
                pageCollection.Add(new PageNumber("  5  "));

                this.DataContext = this;
            }

            public ObservableCollection<PageNumber> PageCollection
            {
                get { return this.pageCollection; }
                set 
                { 
                    this.pageCollection = value;
                    this.OnPropertyChanged("PageCollection");
                }
            }

            private int currentPage;
            public int CurrentPage
            {
                get { return currentPage; }
                set 
                { 
                    currentPage = value;
                    this.OnPropertyChanged("CurrentPage");
                }
            }

            private void button1_Click(object sender, RoutedEventArgs e)
            {
   #region --  IF I COMMENT THIS MUCH CODE THEN THERE IS NO PROBLEM,,,PROBLEM OCCURES WHEN I UNCOMMENT THE CODE,,, --
            pageCollection.Clear();

            pageCollection.Add(new PageNumber("  0  "));
            pageCollection.Add(new PageNumber("  1  "));
            pageCollection.Add(new PageNumber("  2  "));
            #endregion


                for (int i = 0; i < pageControl.Items.Count; i++)
                {
                    var container = pageControl.ItemContainerGenerator.ContainerFromIndex(i) as ContentPresenter;
                    var button = container.ContentTemplate.FindName("pageNumberButton", container) as Button;

                    if (button.Content.Equals(string.Format("  {0}  ", currentPage)))
                    {
                        button.Background = Brushes.NavajoWhite;
                    }
                    else
                    {
                        button.Background = nextButton.Background;
                    }
                }
                currentPage++;
            }



            #region --  INotifyPropertyChanged Members  --

            public event PropertyChangedEventHandler PropertyChanged;

            public void OnPropertyChanged(string propertyNameArg)
            {
                PropertyChangedEventHandler handler = this.PropertyChanged;
                if (handler != null)
                {
                    handler(this,new PropertyChangedEventArgs(propertyNameArg));
                }
            }
            #endregion
        }

        public class PageNumber 
        {
            private string page_Number;
            public PageNumber(string pageNumberArg)
            {
                this.page_Number = pageNumberArg;
            }
            public string Page_Number
            {
                get { return page_Number; }
                set 
                {
                    page_Number = value; 
                }
            }
        } 

【问题讨论】:

  • 我有这样的场景,当按钮(下一个按钮)被点击 CurrentPage 时,为了向用户显示 CurrentPage,我正在更改 Buttonbackground,其内容等于CurrentPage。谢谢....

标签: c# .net wpf xaml styles


【解决方案1】:

从 DependencyObject 派生的对象上不需要 INotifyPropertyChanged 接口。您应该改用 DependencyProperty。

更改整个 ObservableCollection 不是一个好习惯,所以创建一个并且不要破坏它:改为清除。

访问托管在 ItemsControl 中的项目(更一般地说是可视化树中的任何内容)是一种错误的做法。在按钮单击处理程序中只需编写以下内容:

Button btn = (Button)e.OriginalSource;
PageNumber pn = (PageNumber)btn.DataContext;
this.CurrentPage = pn.Page;

但是,您必须在 PageNumber 类中添加一个名为“Page”(类型“int”)的新属性。

要控制按钮颜色,我会使用 MultiBinding 转换器。

public class ButtonColorConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        int current = (int)values[0];
        int button = (int)values[1];

        return button == current
            ? Brushes.NavajoWhite
            : Brushes.XXX;  //set the desired color

    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

但是,必须相应地更改 XAML:

<ItemsControl.ItemTemplate>
  <DataTemplate>
    <Button x:Name="pageNumberButton" Margin="3,4" Style="{StaticResource buttonStyle}" Content="{Binding Path=Page_Number}">
      <Button.Background>
        <MultiBinding Converter="{StaticResource xxx}">  //specify the converter seen above
          <Binding Path="CurrentPage" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}" />
          <Binding Path="Page" />
        </MultiBinding>
      </Button.Background>
    </Button>
  </DataTemplate>
</ItemsControl.ItemTemplate>

我没有测试这个程序,但它应该可以工作。

干杯

【讨论】:

  • 我会点击nextButton而不是我怎么能得到它的DataContext...因为你建议将以下代码放入Click eventButtonbtn = (Button)e.OriginalSource; PageNumber pn = (PageNumber)btn.DataContext; this.CurrentPage = pn.Page;........ ....非常感谢您的回答
  • ,,, 非常感谢您的回答.....顺便说一句,有没有办法将特定按钮的 background 颜色从窗口传递到 Convertor 例如ButtonColorConverter。 ......谢谢......
  • 没那么简单。您可以在 Window.Resources 中声明一个 SolidColorBrush,然后将它用于“下一步”按钮和转换器。为此,请将 ConverterParameter="{StaticResource yourbrush}" 添加到 MultiBinding 元素。在转换器类中,您可以通过将“参数”参数转换为 Brush 来获取画笔。
【解决方案2】:

根据 Mario 的 建议,我使用了一个转换器,它工作正常。 看看下面的代码。根据我的要求可以正常工作...

谢谢马里奥

MainWindow.Xaml

<Window x:Class="CurrentPageProblem.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        xmlns:Local="clr-namespace:CurrentPageProblem">
    <Window.Resources>
        <Local:ButtonColorConverter x:Key="myConverter">

        </Local:ButtonColorConverter>
        <Style TargetType="Button" x:Key="buttonStyle">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <Border  CornerRadius="2,2,2,2"  HorizontalAlignment="Center" x:Name="borderTemplate" Background="{TemplateBinding Background}">
                            <ContentPresenter/>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="true">
                                <Setter TargetName="borderTemplate"  Property="Border.BorderBrush" Value="Gray" />
                                <Setter TargetName="borderTemplate"  Property="Border.BorderThickness" Value="1" />
                            </Trigger>
                            <Trigger Property="IsPressed" Value="true">
                                <Setter TargetName="borderTemplate"  Property="Border.BorderBrush" Value="Lime" />
                            </Trigger>
                            <Trigger Property="IsFocused" Value="true">
                                <Setter TargetName="borderTemplate"  Property="Border.Background" Value="#FD7" />
                            </Trigger>
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter TargetName="borderTemplate"  Property="Border.Background" Value="LightGray"></Setter>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="47*" />
            <RowDefinition Height="264*" />
        </Grid.RowDefinitions>
        <ItemsControl Name="pageControl" ItemsSource="{Binding Path=PageCollection}" Grid.Row="0">
            <ItemsControl.Template>
                <ControlTemplate TargetType="ItemsControl">
                    <Border >
                        <StackPanel>
                            <ItemsPresenter></ItemsPresenter>
                        </StackPanel>
                    </Border>
                </ControlTemplate>
            </ItemsControl.Template>
            <ItemsControl.ItemsPanel x:Uid="pageItemTemplate">
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Horizontal"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Button x:Name="pageNumberButton" Margin="3,4" Style="{StaticResource buttonStyle}" Content="{Binding Path=Page_Number}">
                        <Button.Background>
                            <MultiBinding Converter="{StaticResource myConverter}">
                                <Binding Path="CurrentPage" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}" />
                                <Binding Path="Page_Number" />
                            </MultiBinding>
                        </Button.Background>
                    </Button>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

        <Button Content="Next" Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="136,98,0,0" Name="nextButton" VerticalAlignment="Top" Width="75" Click="button1_Click" />
    </Grid>
</Window>

MainWindow.Xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;

namespace CurrentPageProblem
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        ObservableCollection<PageNumber> pageCollection = new ObservableCollection<PageNumber>();
        public MainWindow()
        {
            InitializeComponent();

            pageCollection.Add(new PageNumber("  0  "));
            pageCollection.Add(new PageNumber("  1  "));
            pageCollection.Add(new PageNumber("  2  "));
            pageCollection.Add(new PageNumber("  3  "));
            pageCollection.Add(new PageNumber("  4  "));
            pageCollection.Add(new PageNumber("  5  "));

            this.DataContext = this;
        }

        public ObservableCollection<PageNumber> PageCollection
        {
            get { return this.pageCollection; }
            set 
            { 
                this.pageCollection = value;

            }
        }

        private int currentPage;
        public int CurrentPage
        {
            get { return currentPage; }
            set 
            { 
                currentPage = value;

            }
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {

            #region -- THIS CODE WORKS FINE NOW --
            pageCollection.Clear();

            pageCollection.Add(new PageNumber("  0  "));
            pageCollection.Add(new PageNumber("  1  "));
            pageCollection.Add(new PageNumber("  2  "));
            pageCollection.Add(new PageNumber("  3  "));
            pageCollection.Add(new PageNumber("  4  "));
            pageCollection.Add(new PageNumber("  5  "));
            pageCollection.Add(new PageNumber("  6  "));
            pageCollection.Add(new PageNumber("  7  "));
            pageCollection.Add(new PageNumber("  8  "));
            pageCollection.Add(new PageNumber("  9  "));
            #endregion

            currentPage++;

        }

    }
    public class ButtonColorConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            string current = string.Format("  {0}  ", values[0]);
            string button = (string)values[1];


            return button == current
                ? Brushes.NavajoWhite
                : Brushes.White;  //set the desired color

        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    public class PageNumber 
    {
        private string page_Number;
        public PageNumber(string pageNumberArg)
        {
            this.page_Number = pageNumberArg;
        }
        public string Page_Number
        {
            get { return page_Number; }
            set 
            {
                page_Number = value; 
            }
        }
    }
}

【讨论】:

    猜你喜欢
    • 2021-10-03
    • 1970-01-01
    • 1970-01-01
    • 2014-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多