我有一個ObservableCollection的DataPoint物件。該類有一個Data屬性。我有一個DataGrid. 我有一個名為 的自定義 UserControl NumberBox,它是一個TextBox但用于數字的包裝器,具有Value可系結(或至少打算系結)的屬性。
我希望在列中DataGrid顯示 my ,以便可以顯示和更改該值。我使用了,將屬性系結到,將 設定為我的.DataNumberBoxDataGridTemplateColumnValueDataItemsSourceObservableCollection
當底層Data被添加或修改時,NumberBox更新就好了。但是,當我在框中輸入一個值時,Data它不會更新。
我找到了建議實施INotifyPropertyChanged. 首先,不確定我應該實施什么。其次,我想實作它正是如此兩個我DataPoint和我的NumberBox。我找到了建議添加Mode=TwoWay, UpdateSourceTrigger=PropertyChange到我的Value系結的答案。我已經嘗試過這兩種方法,分別和一起嘗試。顯然,問題依然存在。
下面是我目前用來嘗試使這件事起作用的最低限度的專案。我錯過了什么?
主視窗.xaml
<Window xmlns:BindingTest="clr-namespace:BindingTest" x:Class="BindingTest.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">
<Grid>
<DataGrid Name="Container" AutoGenerateColumns="False" CanUserSortColumns="False" CanUserResizeColumns="False" CanUserResizeRows="False" CanUserReorderColumns="False" CanUserAddRows="False" CanUserDeleteRows="True">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Sample Text" Width="100" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<BindingTest:NumberBox Value="{Binding Data}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<Button Name="BTN" Click="Button_Click" Height="30" VerticalAlignment="Bottom" Content="Check"/>
</Grid>
</Window>
主視窗.cs
public partial class MainWindow : Window
{
private ObservableCollection<DataPoint> Liste { get; set; }
public MainWindow()
{
InitializeComponent();
Liste = new ObservableCollection<DataPoint>();
Container.ItemsSource = Liste;
DataPoint dp1 = new DataPoint(); dp1.Data = 1;
DataPoint dp2 = new DataPoint(); dp2.Data = 2;
Liste.Add(dp1);
Liste.Add(dp2);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
BTN.Content = Liste[0].Data;
}
}
資料點.cs
public class DataPoint
{
public double Data { get; set; }
}
數字框.xaml
<UserControl x:Class="BindingTest.NumberBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="28" d:DesignWidth="200">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBox Name="Container" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" VerticalContentAlignment="Center"/>
</Grid>
</UserControl>
數字框.cs
public partial class NumberBox : UserControl
{
public event EventHandler ValueChanged;
public NumberBox()
{
InitializeComponent();
}
private double _value;
public double Value
{
get { return _value; }
set
{
_value = value;
Container.Text = value.ToString(CultureInfo.InvariantCulture);
if (ValueChanged != null) ValueChanged(this, new EventArgs());
}
}
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
"Value",
typeof(double),
typeof(NumberBox),
new PropertyMetadata(OnValuePropertyChanged)
);
public static void OnValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
double? val = e.NewValue as double?;
(d as NumberBox).Value = val.Value;
}
}
uj5u.com熱心網友回復:
我錯過了什么?
其實有好幾件事。
依賴屬性的 CLR 屬性應該只獲取和設定依賴屬性的值:
public partial class NumberBox : UserControl { public NumberBox() { InitializeComponent(); } public double Value { get => (double)GetValue(ValueProperty); set => SetValue(ValueProperty, value); } public static readonly DependencyProperty ValueProperty = DependencyProperty.Register( "Value", typeof(double), typeof(NumberBox), new PropertyMetadata(0.0) ); private void Container_PreviewTextInput(object sender, TextCompositionEventArgs e) { Value = double.Parse(Container.Text, CultureInfo.InvariantCulture); } }將
TextBox在控制應系結到的Value屬性:<TextBox Name="Container" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" VerticalContentAlignment="Center" Text="{Binding Value, RelativeSource={RelativeSource AncestorType=UserControl}}" PreviewTextInput="Container_PreviewTextInput"/>Value和Data屬性之間的系結模式應該設定為TwoWay和,這是因為輸入控制元件在 的CellTemplate中DataGrid,所以UpdateSourceTrigger應該設定為PropertyChanged:<local:NumberBox x:Name="nb" Value="{Binding Data, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
uj5u.com熱心網友回復:
mm8 的回答為我指明了正確的方向。
兩個關鍵的缺失元素確實是:更改TextBoxNumberBox.xaml 中的諸如
<TextBox Name="Container"
Text="{Binding Value, RelativeSource={RelativeSource AncestorType=UserControl}}"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch" VerticalContentAlignment="Center"
/>
并更改 MainWindow.xaml 中的系結,例如
...
<DataTemplate>
<BindingTest:NumberBox
Value="{Binding Data, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
...
有了這兩項修改,無論是Value和Data正在更新我的內雙的方式DataGridTemplaceColumn。
然而,系結到文本被證明是有問題的。無論您的系統如何設定,WPF 顯然都使用 en-US 文化,這非常糟糕,因為此控制元件處理數字。使用這個技巧解決了這個問題,現在可以識別正確的小數點分隔符。就我而言,我已將它添加到靜態建構式中以達到相同的效果,因此 NumberBox 可以按原樣用于其他應用程式。
static NumberBox()
{
FrameworkElement.LanguageProperty.OverrideMetadata(
typeof(FrameworkElement),
new FrameworkPropertyMetadata(XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));
}
我已經在我的測驗專案中對此進行了測驗,然后再次測驗了與我的實際專案的集成。據我所知,它成立,所以我會考慮回答這個問題。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/313954.html
