[英]Reducing multiple windows with mvvm
我有一個帶有幾個按鈕的主窗口,每個按鈕代表不同的對象(同一種),它們需要不同的圖形值。使用一個視圖和窗口以在同一對象上呈現所有不同對象的最佳方法是什么圖(當然是一個時間)取決於我們選擇的按鈕。
這是視圖(在我看來,刪除XAML代碼對於該問題而言是不必要的):
<layout:SampleLayoutWindow x:Class="AreaChart.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
ResizeMode="CanResizeWithGrip"
xmlns:chart="clr-namespace:Syncfusion.UI.Xaml.Charts;assembly=Syncfusion.SfChart.WPF"
xmlns:local="clr-namespace:PL"
xmlns:layout="clr-namespace:Syncfusion.Windows.SampleLayout;assembly=Syncfusion.Chart.Wpf.SampleLayout"
UserOptionsVisibility="Collapsed"
WindowStartupLocation="CenterScreen" Height="643.287" Width="1250.5"
Title="2017">
<Grid>
<Grid.Resources>
...........................................
<chart:AreaSeries x:Name="AreaSeries" EnableAnimation="True"
**XBindingPath="date"
Label="Favourite"
YBindingPath="rate"
ItemsSource="{Binding CurrenciesHis}"**
ShowTooltip="True" >
<chart:AreaSeries.AdornmentsInfo>
<chart:ChartAdornmentInfo AdornmentsPosition="Bottom"
HorizontalAlignment="Center"
VerticalAlignment="Center"
ShowLabel="True">
<chart:ChartAdornmentInfo.LabelTemplate>
<DataTemplate>
....................................
<ComboBox
ItemsSource="{Binding YearsList}"
SelectedItem="{Binding Year}"
/>
這是ViewModel:
public class ViewModel
{
public ViewModel()
{
Year = DateTime.Now.Year - 1;
UpdateCurrencies();
}
protected void UpdateCurrencies()
{
// Indexs that holds actuall api retrived values
int i, j;
// cR- current rate in string format, urlContents - the whole Api retrived data
string cR, urlContents;
// For api syntx, add 0 or not, depends on the current date syntax
string c;
CurrenciesHis = new ObservableCollection<Model>();//Model objects collection
HttpClient client = new HttpClient();
for (int l = 1; l < 13; l++)
{
if (l < 10)
c = "0";
else
c = "";
// Use the public property Year, not the field _year
var url = "http://data.fixer.io/api/" + Year + "-" + c + l + "-01?access_key=&base=USD&symbols=EUR&format=1";
urlContents = client.GetStringAsync(url).Result;
i = urlContents.IndexOf("EUR");//Finds the desired value from api recived data
j = urlContents.IndexOf("}");
cR = urlContents.Substring(i + 5, (j - 2) - (i + 5));
CurrenciesHis.Add(new Model() { rate = Convert.ToDouble(cR), date = "01/" + l.ToString() });
}
OnPropertyChanged(nameof(CurrenciesHis));
}
private int _year;
public int Year
{
get { return _year; }
set
{
if (_year != value)
{
_year = value;
OnPropertyChanged(nameof(Year));
UpdateCurrencies();
}
}
}
public ObservableCollection<Model> CurrenciesHis { get; private set; }
public System.Collections.IEnumerable YearsList
=> Enumerable.Range(DateTime.Now.Year - 30, 30).ToList().AsReadOnly();
}
這是主窗口,我們通過單擊打開包含圖形的窗口的按鈕,選擇了要在視圖的圖形上表示的貨幣:
<Window x:Class="PL.WindowMenu"
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:PL"
mc:Ignorable="d"
Title="WindowMenu" Height="643.287" Width="1250.5" WindowStartupLocation="CenterScreen">
<StackPanel Margin="0,0,2,2" RenderTransformOrigin="0.511,0.536">
<StackPanel.Background>
<ImageBrush/>
</StackPanel.Background>
<Grid Height="612" x:Name="NewGrid">
<Button Style="{StaticResource ButtonStyle}" HorizontalAlignment="Left" Height="92" Margin="346,221,0,0" VerticalAlignment="Top" Width="290" Click="Button_Click"></Button>
<Button Style="{StaticResource ButtonStyle}" HorizontalAlignment="Left" Height="92" Margin="346,221,0,0" VerticalAlignment="Top" Width="290" Click="Button_Click2" Command="{Binding Path=ButtonClickCommand}" CommandParameter="{Binding}"></Button>
<Button Style="{StaticResource ButtonStyle}" HorizontalAlignment="Left" Height="92" Margin="346,221,0,0" VerticalAlignment="Top" Width="290" Click="Button_Click3"></Button>
</Grid>
</stackpanel>
</window>
主窗口的ViewModel:
class RTViewModel : ObservableCollection<RTModel>
{
IBL bl;
public ICommand ButtonClickCommand
{
get
{
return new EuroClickCommand();
}
}
public void OpenGraph()
{
AreaChart.MainWindow myWindow = new AreaChart.MainWindow();
myWindow.Show();
//Window.GetWindow(this).Hide();
}
public RTViewModel()
{
}
EuroClickCommand:
class EuroClickCommand : ICommand
{
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
var viewModel = (RTViewModel)parameter;
viewModel.OpenGraph();
}
}
執行此任務的最佳方法是什么?
您有幾種選擇可以實現此目的 。 一種是在視圖中顯示多個圖形,其中一個具有Visibility = Visibility.Visible
,另一個具有Visibility.Collapsed
。 如果您的圖表有所不同,那很好。
但是另一種資源較少的解決方案是僅更改綁定的ObervableCollection 。 我建議在以下MVVM實現中使用按鈕來更改圖形。
在您看來:
<chart:AreaSeries ItemsSource="{Binding CurrenciesHis}"/>
<Button Command="{Binding ChooseGraphCommand}" CommandParameter="1"/>
<Button Command="{Binding ChooseGraphCommand}" CommandParameter="2"/>
<Button Command="{Binding ChooseGraphCommand}" CommandParameter="3"/>
並在您的ViewModel中:
private ValuesType _currenciesHis;
public ValuesType CurrenciesHis
{
get => _currenciesHis;
set
{
if (value == _currenciesHis) return;
_currenciesHis = value;
OnPropertyChanged();
}
}
private ICommand _chooseGraphCommand;
public ICommand ChooseGraphCommand => _chooseGraphCommand ??
(_chooseGraphCommand= new DelegateCommand(
s =>
{
switch(s)
{
default:
case 1:
CurrenciesHis = graph1; // graph1 contains your data
case 2:
CurrenciesHis = graph2;
case 3:
CurrenciesHis = graph3;
}
// or
CurrenciesHis = allGraphs[s-1]; // array or List of your data
},
s => true));
// implementation of INPC
public event PropertyChangedEventHandler PropertyChanged;
[YourNameSpace.Annotations.NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
和這個輔助類:
public class DelegateCommand : ICommand
{
private readonly Predicate<object> _canExecute;
private readonly Action<object> _execute;
public event EventHandler CanExecuteChanged;
public DelegateCommand(Action<object> execute) : this(execute, null) {}
public DelegateCommand(Action<object> execute, Predicate<object> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter) => _canExecute == null || _canExecute(parameter);
public void Execute(object parameter) => _execute(parameter);
public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
但是,在您的注釋中:
[AttributeUsage(AttributeTargets.Method)]
public sealed class NotifyPropertyChangedInvocatorAttribute : Attribute
{
public NotifyPropertyChangedInvocatorAttribute() { }
public NotifyPropertyChangedInvocatorAttribute([NotNull] string parameterName)
{
ParameterName = parameterName;
}
[CanBeNull] public string ParameterName { get; private set; }
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.