【问题标题】:DataGridTextColumn showing/editing time only, date bound to property of parent usercontrolDataGridTextColumn 仅显示/编辑时间,日期绑定到父用户控件的属性
【发布时间】:2013-06-06 23:34:24
【问题描述】:

我在UserControl 中有一个DataGrid。我想让DataGridTextColumn 绑定到DateTime 字段,只显示时间。当用户输入时间时,日期部分(年、月、日)应取自 UserControl 上的属性 (AttendDate)。

我的第一个想法是将用户控件的属性绑定到ConverterParameter:

<DataGridTextColumn Header="From" 
    Binding="{Binding FromDate, Converter={StaticResource TimeConverter},ConverterParameter={Binding AttendDate,ElementName=UC}}"
/>

但是ConverterParameter 没有绑定。然后我想使用MultiBinding:

<DataGridTextColumn Header="משעה" Binding="{Binding FromDate, Converter={StaticResource TimeConverter}}" />
    <DataGridTextColumn.Binding>
        <MultiBinding Converter="{StaticResource TimeConverter}">
            <Binding Path="FromDate" />
            <Binding Path="AttendDate" ElementName="UC" />
        </MultiBinding>
    </DataGridTextColumn.Binding>
</DataGridTextColumn>

然而IMultiValueConverter.Convert——它接受多个参数——仅在格式化显示时被调用。 IMultiValueConverter.ConvertBack 是在编辑时调用的,只接受一个参数 - 输入的字符串。

我该怎么做?

(我没有使用 MVVM;我无法更改。)

【问题讨论】:

    标签: wpf binding


    【解决方案1】:

    解决方案的一个想法是让另一个属性只有一个 getter 来合并您想要的信息。

    类似

    property string Time {get {return this.FromDate.toshortdate().tostring() + AttendDate.hour.tostring() + attenddate.minutes.tostring()}; }
    

    代码可能不完全是这样,但是你可以绑定这个属性来显示你想要的信息应该出现在哪里。

    问候,

    =============编辑===========

    我试过这个,一个非常简单的例子……不知道它是否适合你:

    XAML:

    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:conv ="clr-namespace:WpfApplication1"
            Title="MainWindow" Height="350" Width="525">
        <Window.Resources>
            <conv:TimeConverter x:Key="tmeConverter"></conv:TimeConverter>
        </Window.Resources>
    
        <Grid>
            <DataGrid ItemsSource="{Binding listExample}">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="teste" >
                        <DataGridTextColumn.Binding>
                            <MultiBinding Converter="{StaticResource tmeConverter}">
                                <Binding Path="FromDate" />
                                <Binding Path="AttendDate" />
                            </MultiBinding>
                        </DataGridTextColumn.Binding>
                    </DataGridTextColumn>
                </DataGrid.Columns>
            </DataGrid>
        </Grid>
    </Window>
    

    代码隐藏 (.cs)

    namespace WpfApplication1
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            public List<Example2> listExample { get; set; }
    
            public Example2 Test { get; set; }
    
            public MainWindow()
            {
                InitializeComponent();
                this.listExample = new List<Example2>();
                //listExample.Add(new Example { IsChecked = false, Test1 = "teste" });
                //listExample.Add(new Example { IsChecked = false, Test1 = "TTTTT!" });
    
                this.Test = new Example2 { AttendDate = "1ui", FromDate = "ff" };
                this.listExample.Add(this.Test);
    
                DataContext = this;
    
    
            }
        }
    }
    

    还有 Example2 类:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace WpfApplication1
    {
        public class Example2
        {
            public string FromDate { get; set; }
    
            public string AttendDate { get; set; }
        }
    }
    

    转换器:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Data;
    
    namespace WpfApplication1
    {
        class TimeConverter : IMultiValueConverter
        {
            public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                return values[0].ToString() + values[1].ToString();
            }
    
            public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
            {
                throw new NotImplementedException();
            }
        }
    }
    

    最后的窗口出现3列,如果我改变最后两列,第一列会自动编辑。

    是吗?

    【讨论】:

    • 我用自定义格式显示值没有问题;我可以用 MultiBinding 做到这一点。我的问题是实际值需要根据AttendDate属性的值来改变。
    • 然后,您必须实现 INotifyPropertyChanged。检查 stackoverflow.com/questions/16787757/… ,具有示例类的部分。
    • 一个问题,你试过 吗?
    • 是的,我有;这是我的问题。
    • 我在你的问题中看不到。无论如何,如果您愿意,我可以尝试制作一个可行的示例:)
    【解决方案2】:

    摆脱 DataGridTextColumn 并将 DataGridTemplateColumn 与包含绑定到多重绑定的文本块的 CellTemplate 和包含绑定到 FromDate 的 TextBox 的单元格编辑模板一起使用,可能通过短日期转换器,具体取决于您打算实现的可用性。

    关于可能的解决方案:

    XAML

        <StackPanel>
        <StackPanel Orientation="Horizontal">
            <Label>From time</Label>
            <DatePicker SelectedDate="{Binding FromTime}"/>
        </StackPanel>
        <DataGrid ItemsSource="{Binding AllUsers}" AutoGenerateColumns="False">
            <DataGrid.Resources>
                <local:TimeConverter x:Key="TimeConverter"/>
            </DataGrid.Resources>
            <DataGrid.Columns>
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate DataType="local:UserViewModel">
                            <TextBlock>
                                <TextBlock.Text>
                                    <MultiBinding Converter="{StaticResource TimeConverter}">
                                        <Binding ElementName="root" Path="DataContext.FromTime"/>
                                        <Binding Path="AttendTimeHour"/>
                                        <Binding Path="AttendTimeMinute"/>
                                    </MultiBinding>
                                </TextBlock.Text>
                            </TextBlock>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                    <DataGridTemplateColumn.CellEditingTemplate>
                        <DataTemplate DataType="local:UserViewModel">
                            <StackPanel Orientation="Horizontal">
                                <TextBlock>
                                    <Run>Attend on </Run>
                                    <Run Text="{Binding ElementName=root, Path=DataContext.FromTime, StringFormat=d}"/>
                                    <Run> at </Run>
                                </TextBlock>
                                <TextBox Text="{Binding AttendTimeHour}"/><TextBlock>:</TextBlock>
                                <TextBox Text="{Binding AttendTimeMinute}"/>
                            </StackPanel>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellEditingTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </StackPanel>
    

    视图模型(UserViewModel)部分:

        private DateTime _attendTime;
    
        public DateTime AttendTime
        {
            get { return _attendTime; }
            set
            {
                if (value == _attendTime) return;
                _attendTime = value;
                OnPropertyChanged();
                OnPropertyChanged("AttendTimeHour");
                OnPropertyChanged("AttendTimeMinute");
            }
        }
    
        public int AttendTimeHour
        {
            get { return attendTimeHour; }
            set
            {
                if (value.Equals(attendTimeHour)) return;
                attendTimeHour = value;
                AttendTime = new DateTime(AttendTime.Year, AttendTime.Month, AttendTime.Day, AttendTimeHour, AttendTime.Minute, AttendTime.Second);
                OnPropertyChanged();
            }
        }
    
        private int _attendTimeMinute;
    
        public int AttendTimeMinute
        {
            get { return _attendTimeMinute; }
            set
            {
                if (value == _attendTimeMinute) return;
                _attendTimeMinute = value;
                AttendTime = new DateTime(AttendTime.Year, AttendTime.Month, AttendTime.Day, AttendTime.Hour, AttendTimeMinute, AttendTime.Second);
                OnPropertyChanged();
            }
        }
    

    还有转换器

        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            if (values.Length < 2) return null;
            if (!(values[0] is DateTime && values[1] is int && values[2] is int)) return null;
    
            var fromDate = (DateTime) values[0];
            var attendTimeHour = (int) values[1];
            var attendTimeMinutes = (int)values[2];
    
            var result = new DateTime(fromDate.Year, fromDate.Month, fromDate.Day, attendTimeHour, attendTimeMinutes, 0);
            return result.ToString();
        }
    

    【讨论】:

    • 用户是否还需要输入完整的日期时间,而不仅仅是时间?
    • 如果在模板列中使用 celleditingtemplate,您可以完全控制 UI 将如何呈现给用户,因此用户必须输入的内容仅取决于开发人员在 UI 中给他的内容.我已经用一个可能变体的简单示例更新了我的答案。由于 DateTime 的不可变性质,有一些技巧,但我认为你会抓住 ided
    猜你喜欢
    • 1970-01-01
    • 2012-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多