【问题标题】:Rectangle inside DataGrid, bind width value of rectangleDataGrid内的矩形,绑定矩形的宽度值
【发布时间】:2021-01-10 00:45:47
【问题描述】:

我正在尝试将矩形宽度属性绑定到一个变量,因此随着每个添加到数据网格的记录,矩形的宽度是不同的(图表样式)。我什至无法使用x:Name 访问这个矩形。

XAML:

<DataGrid.Columns>
   <DataGridTextColumn Binding="{Binding Path=Data}" Header="Data"  ></DataGridTextColumn>
   <DataGridTextColumn Binding="{Binding Path=Pamaina}" Header="Pamaina"></DataGridTextColumn>
   <DataGridTextColumn Binding="{Binding Path=TyrimoVieta}" Header="Tyrimo vieta"></DataGridTextColumn>
   <DataGridTextColumn Binding="{Binding Path=Koncentracija}" Header="Koncentacija"></DataGridTextColumn>
   <DataGridTemplateColumn Header="Rect">
      <DataGridTemplateColumn.CellTemplate>
         <DataTemplate>
            <StackPanel x:Name="assTR">
               <Rectangle Width="{Binding ilgis}" Height="10" Fill="Green" />
            </StackPanel>
         </DataTemplate>
      </DataGridTemplateColumn.CellTemplate>
   </DataGridTemplateColumn>
</DataGrid.Columns>

C#

List<DatagridItems> datagridItems = new List<DatagridItems>();
public class DatagridItems
{
   public string Data { get; set; }
   public string Pamaina { get; set; }
   public string TyrimoVieta { get; set; }
   public string Koncentracija { get; set; }
}

public List<DatagridItems> LoadCollectionData(string data, string pamaina, string tyrimovieta, string koncentracija)
{
   Datagrid_1.Items.Refresh(); //du refresh kad atsinaujintu kolekcija
   datagridItems.Add(new DatagridItems()
   {
      Data = data,
      Pamaina = pamaina,
      TyrimoVieta = tyrimovieta,
      Koncentracija = koncentracija,
   });
   Datagrid_1.Items.Refresh();

   return datagridItems;
}

调用填充数据网格

Datagrid_1.ItemsSource = LoadCollectionData(datosFormatas, row["pamaina"].ToString(), tyrimoVieta_isFunkcijos, koncentracija);

我实际上不知道这是否会达到我想要的效果。下面是我试图实现的图片。我想要“Koncentracija”中的值来设置绿色矩形的宽度。这甚至可以做到吗?我设法只绘制了静态宽度的矩形。

感谢任何帮助。 Image of what i am trying to achieve

【问题讨论】:

    标签: c# wpf datagrid


    【解决方案1】:

    我希望“Koncentracija”中的值设置绿色矩形的宽度。这也能做到吗?

    可以的。

    基本上,您希望将string 类型变量与将代表矩形的width 的变量绑定。怎么样?

    通常宽度用数值表示;)

    所以最简单的解决方案 - 您需要将 Koncentracija 属性的数据类型更改为 @thatguy 指出的 intdecimal。但是为了在不使用转换器的情况下保持简单 - 您必须提供一种机制来通知您的视图属性已更改。

    最简单的方法是实现INotifyPropertyChanged 接口并使用属性名称调用setter 中的propertychanged 事件,如下所示:

    public class DataGridViewItem : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        protected void RaisePropertyChanged(string property)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
        }
    
        public string Data { get; set; }
        public string Pamaina { get; set; }
        public string TyrimoVieta { get; set; }
    
        private int koncentracija;
        public int Koncentracija
        {
            get { return koncentracija; }
            set
            {
                koncentracija = value;
                RaisePropertyChanged(nameof(Koncentracija));
            }
        }
    }
    

    我制作了一个简单的视图来表示向 DataGrid 添加一个元素,该元素通过单击一个按钮来更改矩形的宽度。这是查看代码:

    <Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <DataGrid Name="MyDataGrid" HorizontalAlignment="Left" Height="150" Margin="44,74,0,0" VerticalAlignment="Top" Width="171"/>
        <Rectangle Name="MyRectangle" Fill="Green" HorizontalAlignment="Left" Width="{Binding Koncentracija}" Height="47" Margin="350,91,0,0" Stroke="Black" VerticalAlignment="Top" />
        <Button Name="AddItemBtn" Content="AddToDataGrid" Margin="63,281,615.6,0" VerticalAlignment="Top" Width="115" Height="53" FontSize="16" Click="AddItemBtn_Click"/>
    </Grid>
    

    现在在您的视图后面的代码中(在我的示例“MainWindow.xaml.cs”中)有一个简单的逻辑,您可以根据您的问题进行调整。在这里,我将 Koncentracija 值增加了 30,但是您可以通过从所需对象获取数据来做到这一点。

    代码:

     public partial class MainWindow : Window
    {
        DataGridViewItem dataItem = new DataGridViewItem();
        List<Person> people = new List<Person>() { new Person { Name = "Mark", Age = 12 }, new Person { Name = "Chris", Age = 22 } };
    
        public MainWindow()
        {
            InitializeComponent();
            MyDataGrid.ItemsSource = people;
            DataContext = dataItem;
        }
    
        private void AddItemBtn_Click(object sender, RoutedEventArgs e)
        {
            people.Add(new Person() { Name = "Tom", Age = 27 });
            dataItem.Koncentracija += 30;
            MyDataGrid.Items.Refresh();
        }
    }
    

    这是一张图片https://ibb.co/B4FCD6S 希望对你有帮助:)

    *编辑:我建议您在创建 WPF 应用程序时熟悉 MVVM 模式,因为它对您有很大帮助。这里有一个教程:https://www.tutorialspoint.com/mvvm/index.htm

    【讨论】:

    • 感谢您提供详细信息。我最终在我的班级中创建了 Width decimal 的唯一原因是因为 Koncentracija 值太小而无法在图表中使用。宽度 = Koncentracija * 4。必须深入研究这个 MVVM 模式。干杯。 link
    【解决方案2】:

    您需要创建一个自定义DataGridTemplateColumn。你可以在DataTemplate里面放任何你想要的东西。

    这行得通:

    MainWindow.xaml

    <DataGrid ItemsSource="{Binding Items}" AutoGenerateColumns="False" IsReadOnly="True">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Name" Binding="{Binding Name}">
            </DataGridTextColumn>
            <DataGridTemplateColumn Header="Width">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Rectangle Width="{Binding Width}" Height="10" Fill="Blue" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
    
    

    MainWindowVM.cs

    using GalaSoft.MvvmLight;
    using System.Collections.Generic;
    
    namespace WpfApp1
    {
        public class MainWindowVM : ObservableObject
        {
            private List<Item> _Items;
            public List<Item> Items
            {
                get { return _Items; }
                set
                {
                    if (value != _Items)
                    {
                        _Items = value;
                        RaisePropertyChanged();
                    }
                }
            }
            public MainWindowVM()
            {
                Items = new List<Item>()
                {
                    new Item() {Name = "one", Width = 30.5 },
                    new Item() { Name = "two", Width = 10.2 }
                };
    
            }
        }
    
        public class Item : ObservableObject
        {
            private string _Name;
            public string Name
            {
                get { return _Name; }
                set
                {
                    if (value != _Name)
                    {
                        _Name = value;
                        RaisePropertyChanged();
                    }
                }
            }
    
            private double _Width;
            public double Width
            {
                get { return _Width; }
                set
                {
                    if (value != _Width)
                    {
                        _Width = value;
                        RaisePropertyChanged();
                    }
                }
            }
        }
    }
    
    

    结果:

    【讨论】:

      【解决方案3】:

      理想情况下,Koncentracija 属性的类型应为 double 而不是 string,但为此您需要创建一个自定义数据列,该列提供对数字类型的支持以及验证以防止无效值,附加的行为或类型之间的转换。你可以在this post找到解决方案。

      这也允许您简单地将Koncentracija 属性绑定到RectangleWidth,它可以在您的示例中工作。您可以将条形图与HorizontalAlignment 对齐。

      <Rectangle HorizontalAlignment="Left" Width="{Binding Koncentracija}" Height="10" Fill="Green" />
      

      如果您想保持代码不变,可以为Koncentracija 创建一个单向转换器。

      public class StringToDoubleConverter : IValueConverter
      {
         public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
         {
            double.TryParse((string)value, out var result);
            return result;
         }
      
         public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
         {
            throw new InvalidOperationException();
         }
      }
      

      然后,您将为DataGrid 创建此转换器的实例,并将Width 属性绑定到Koncentracija,该转换器会自动将string 转换为double

      <DataGrid ...>
         <DataGrid.Resources>
            <local:StringToDoubleConverter x:Key="StringToDoubleConverter"/>
         </DataGrid.Resources>
         <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding Path=Data}" Header="Data"  ></DataGridTextColumn>
            <DataGridTextColumn Binding="{Binding Path=Pamaina}" Header="Pamaina"></DataGridTextColumn>
            <DataGridTextColumn Binding="{Binding Path=TyrimoVieta}" Header="Tyrimo vieta"></DataGridTextColumn>
            <DataGridTextColumn Binding="{Binding Path=Koncentracija}" Header="Koncentacija"></DataGridTextColumn>
            <DataGridTemplateColumn Header="Rect">
               <DataGridTemplateColumn.CellTemplate>
                  <DataTemplate>
                     <StackPanel x:Name="assTR">
                        <Rectangle HorizontalAlignment="Left" Width="{Binding Koncentracija, Converter={StaticResource StringToDoubleConverter}}" Height="10" Fill="Green" />
                     </StackPanel>
                  </DataTemplate>
               </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
         </DataGrid.Columns>
      </DataGrid>
      

      作为一般说明,您应该在视图模型中implement INotifyPropertyChanged,否则在运行时对属性的更改将不会反映在用户界面中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-20
        • 1970-01-01
        • 2021-08-27
        • 2016-09-29
        • 1970-01-01
        相关资源
        最近更新 更多