从viewModel WPF更新或呈现视图

时间:2016-02-03 14:03:46

标签: c# wpf mvvm

好的,所以这是我的问题: 我有一个WPF应用程序,我正在使用Mvvm模式。在主窗口中,我有一个TabControl,它绑定到一组viewmodel。 Tabcontrol使用contenttemplate使用单独的usercontrol描述每个视图。

现在我想使用按钮将tabcontrol中的每个视图保存到png图像(例如)。问题是 1)如何告诉itemcollection保存每个视图? 2)如何在不特别点击每个tabitem的情况下获取视图(或绑定到各自的datacontext)?

我尝试使用消息处理程序来解决第一个问题,但是,由于所有的tabitems都没有绑定到他们的datacontexts,这意味着第二个问题很难解决。

这是一个例子: 我的主要观点模型:

public class MainViewModel : ViewModelBase {


    public ObservableCollection<SubViewModel> Units { get; private set; }

    public ICommand OnPrintSaveCommand { get; set; }

    public MainViewModel() {
        Units = new ObservableCollection<SubViewModel>
        {
            new SubViewModel(1, "Task 1"),
            new SubViewModel(2, "Task 2"),
            new SubViewModel(3, "Task 3"),
        };

        OnPrintSaveCommand = new RelayCommand( p => PrintSave());
    }

    private void PrintSave() {

        foreach (var subViewModel in Units) {
            subViewModel.OnPrintSave("SomeFileName.bmp");
        }

    }
}

然后我有子视图模型:

public delegate void SaveToPngEventHandler(object sender, SaveToPngEventArgs eventArgs);

public class SubViewModel : ViewModelBase {

    public int UnitNumber { get; private set; }
    public string Unitname { get; private set; }

    private event SaveToPngEventHandler SaveToPngHandler;
    public SaveToPngEventHandler OnSaveToPng { get { return SaveToPngHandler; } set { SaveToPngHandler = value; } }

    public SubViewModel(int unitNumber, string unitname) {
        UnitNumber = unitNumber;
        Unitname = unitname;

        DisplayName = string.Format("{0} - {1}", unitNumber, unitname);
    }

    public void OnPrintSave(string somefilenameBmp) {
        if (OnSaveToPng != null) {
            OnSaveToPng(this, new SaveToPngEventArgs(somefilenameBmp));
        }
    }
}

最后是主窗口:

<Window.Resources>
    <DataTemplate x:Key="UnitTemplate" DataType="local:SubViewModel">
        <local:ItemView/>
    </DataTemplate>

    <Style TargetType="TabItem">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TabItem}">
                    <Border x:Name="Border" CornerRadius="5,0,0,5" BorderBrush="Black" BorderThickness="1" Margin="10">
                        <Grid x:Name="grd">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="Auto"/>
                            </Grid.ColumnDefinitions>
                            <TextBlock x:Name="tb1" Grid.Column="0" Text="{Binding DisplayName}" Margin="2"/>
                            <TextBlock x:Name="tb2" Grid.Column="1" Text="{Binding UnitNumber}" Margin="2"/>
                            <TextBlock x:Name="tb3" Grid.Column="2" Text="{Binding Unitname}" Margin="2"/>

                        </Grid>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter TargetName="Border" Property="Background" Value="Blue"/>
                            <Setter TargetName="tb1" Property="Foreground" Value="White"/>
                            <Setter TargetName="tb2" Property="Foreground" Value="White"/>
                            <Setter TargetName="tb3" Property="Foreground" Value="White"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</Window.Resources>
<Grid>

    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>

    <TabControl Grid.Row="0" ItemsSource="{Binding Units}" TabStripPlacement="Left" ContentTemplate="{StaticResource UnitTemplate}"/>

    <Button Grid.Row="1" VerticalAlignment="Bottom" HorizontalAlignment="Right" Content="Print/save" Margin="5" Command="{Binding OnPrintSaveCommand}"></Button>
</Grid>

和subviewmodel的单独viewcontrol:

<Grid x:Name="MainGrid">
    <Border CornerRadius="5" BorderBrush="Black" BorderThickness="1" Margin="10">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <TextBlock Grid.Column="0" Text="{Binding DisplayName}" Margin="10"/>
            <TextBlock Grid.Column="1" Text="{Binding UnitNumber}" Margin="10"/>
            <TextBlock Grid.Column="2" Text="{Binding Unitname}" Margin="10"/>

        </Grid>
    </Border>
</Grid>

后面的代码:

/// <summary>
/// Interaction logic for ItemView.xaml
/// </summary>
public partial class ItemView : UserControl {
    public ItemView() {
        InitializeComponent();
        this.Loaded += OnLoaded;
    }

    private void OnLoaded(object sender, RoutedEventArgs routedEventArgs) {
        var viewModel = DataContext as SubViewModel;
        if (viewModel != null) {
            viewModel.OnSaveToPng += OnSaveToPng;
            // Will only reach this point if tabitem has been clicked
        }
    }

    private void OnSaveToPng(object sender, SaveToPngEventArgs eventArgs) {
        // Get MainGrid and save it here

        var canvas = new Canvas();
        //canvas.Children.Add(MainGrid);
        // etc..
    }
}

为了运行它,您还需要以下类:

public class RelayCommand : ICommand {
    #region Fields

    readonly Action<object> _execute;
    readonly Predicate<object> _canExecute;

    #endregion // Fields

    #region Constructors

    public RelayCommand(Action<object> execute)
        : this(execute, null) {
    }

    public RelayCommand(Action<object> execute, Predicate<object> canExecute) {
        if (execute == null)
            throw new ArgumentNullException("execute");

        _execute = execute;
        _canExecute = canExecute;
    }
    #endregion // Constructors

    #region ICommand Members

    [DebuggerStepThrough]
    public bool CanExecute(object parameter) {
        return _canExecute == null ? true : _canExecute(parameter);
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public void Execute(object parameter) {
        _execute(parameter);
    }

    #endregion // ICommand Members
}

public class ViewModelBase : INotifyPropertyChanged {

    public string DisplayName { get; set; }

    #region Property Changed

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion
}


public class SaveToPngEventArgs : EventArgs {
    public string FilePath { get; private set; }

    public SaveToPngEventArgs(string filePath) {
        FilePath = filePath;
    }
}

0 个答案:

没有答案