我的情况是有两个控件。您可以在其中设置分钟,然后在其中指定秒数。
它们都应绑定到视图模型中的单个属性。此属性的类型为字符串。该字符串的格式为[hh:mm:ss]。因此,在“分钟”控件中更改值应更改字符串的“mm”部分,并在“秒”控件中更改值应更改字符串的'ss'部分。
提前致谢
答案 0 :(得分:1)
如果您使用TimeSpan
并且其范围介于0到59h 59s之间,则这是一个3属性的ViewModel工作解决方案。我没有完全测试,条件/验证将根据要求进行更改。我使用了TimeSpan.TotalSeconds
,因为这是我们需要的解决方案;这意味着,当将TimeSpan
设置为新值时,我们只需设置通过公共属性的总秒数。另一种方法是在ViewModel中拥有2个TimeSpan
属性,然后在设置公共属性时,可以调用_item.TotalSeconds = VMMinutes.TotalSeconds + VMSeconds.TotalSeconds.TotalSeconds
。基本上你在这里有很多设计选择。
<强> MainWindow.xaml:强>
<Grid>
<StackPanel>
<Border Height="60" BorderBrush="Black" BorderThickness="1">
<StackPanel Orientation="Horizontal">
<Label Content="Minutes"/>
<TextBox Text="{Binding Minutes}" />
<Label Content="Seconds"/>
<TextBox Text="{Binding Seconds}" />
</StackPanel>
</Border>
<Border Height="60" BorderBrush="Black" BorderThickness="1">
<StackPanel Orientation="Horizontal">
<Label Content="Total Seconds"/>
<TextBox Text="{Binding TotalSeconds}" />
</StackPanel>
</Border>
</StackPanel>
</Grid>
<强> MainWindow.xaml.cs 强>:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new ItemViewModel(new Item(new TimeSpan(0, 3, 59)));
}
}
<强> ItemViewModel.cs 强>:
public class ItemViewModel : INotifyPropertyChanged
{
private readonly Item _item;
public event PropertyChangedEventHandler PropertyChanged;
public ItemViewModel(Item item)
{
_item = item;
}
public string TotalSeconds
{
get
{
return _item.TotalSeconds.ToString();
}
set
{
double newTotSecs;
if(!string.IsNullOrEmpty(value))
{
if(double.TryParse(value, out newTotSecs))
{
_item.TotalSeconds = newTotSecs;
NotifyPropertyChanged();
NotifyPropertyChanged("Minutes");
NotifyPropertyChanged("Seconds");
}
}
}
}
public string Seconds
{
get
{
return (_item.TotalSeconds % 60).ToString();
}
set
{
int newVal;
if(!string.IsNullOrEmpty(value))
{
if(int.TryParse(value, out newVal))
{
if(newVal >= 0 && newVal <= 59)
{
int totMinSec;
if(int.TryParse(Minutes, out totMinSec))
{
_item.TotalSeconds = (totMinSec * 60) + newVal;
NotifyPropertyChanged();
NotifyPropertyChanged("TotalSeconds");
}
}
}
}
}
}
public string Minutes
{
get
{
return ((int)(_item.TotalSeconds / 60)).ToString();
}
set
{
int newVal;
if(!string.IsNullOrEmpty(value))
{
if(int.TryParse(value, out newVal))
{
if(newVal >= 0 && newVal <= 59)
{
int totSec;
if(int.TryParse(Seconds, out totSec))
{
_item.TotalSeconds = totSec + (newVal * 60);
NotifyPropertyChanged();
NotifyPropertyChanged("TotalSeconds");
}
}
}
}
}
}
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
<强> Item.cs 强>:
public class Item
{
private TimeSpan _time;
public double TotalSeconds
{
get
{
return _time.TotalSeconds;
}
set
{
if(value >= 0)
{
_time = new TimeSpan(0, 0, (int)value);
}
}
}
public Item(TimeSpan time)
{
_time = time;
}
}
注意:您的另一个选择是使用Converter
,我还没有提供解决方案。我认为从长远来看它可能会变得更干净,因为你真正需要来回传递的是转换器的总秒数。
答案 1 :(得分:1)
我会使用上面的NETScape方法,但将其封装在用户控件中。用户控件XAML类似于:
<UserControl>
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="Minutes" Grid.Row="0" Grid.Column="0"/>
<TextBox Text="{Binding InternalMinutes}" Grid.Row="0" Grid.Column="1"/>
<TextBlock Text="Seconds" Grid.Row="1" Grid.Column="0"/>
<TextBox Text="{Binding InternalSeconds}" Grid.Row="1" Grid.Column="1"/>
</Grid>
</UserControl>
然后在代码隐藏中,您将拥有实际DateTime
对象的依赖属性,以及要绑定的属性(您可以使用视图模型,或者只是从{{1}开始当它的所有View逻辑时,它没问题!)。
示例属性是:
TextChanged
同样,这里有多种方法,您可以使用转换器来使用中间对象。 public int InternalSeconds
{
get { return ExternalTime.Seconds; }
set
{
ExternalTime.Seconds = value;
NotifyPropertyChanged();
}
}
是此处的DP,如果您希望在此控件之外更改值,请务必处理其ExternalTime
事件。