2013-02-19 5 views
8

Vorrei alcuni suggerimenti nella direzione giusta o anche soluzioni pronte a questo problema e sono piuttosto bloccato (sono solo principiante/intermedio):Come emulare una console in WPF?

Sto provando a implementare un SSH nella mia applicazione. Il back-end SSH funziona bene e così, ma sono bloccato al frontend. Quale combinazione WPF mi offre una soluzione adeguata per emulare una console? Mettendo da parte un'emulazione terminale completa, sarei felice di leggere/scrivere in qualcosa che assomiglia a una console :-)

Il mio approccio migliore era ancora una griglia 80x50 di singoli caratteri risultante in 4000 celle singole e che sembra un vero e proprio overkill.

Un'altra idea era creare una console-Appl. associato a una finestra wpf in un altro progetto. Ma ... è anche possibile e come?

+9

Niente assomiglia più a una finestra della console di ... una finestra di console. –

+5

Questo potrebbe essere stato utile se sarebbe stato utile. Per favore, sii così gentile da elaborare. – FrankyTheDumb

+0

Puoi modellare un ListBox e utilizzare i TextBox come elementi e avere l'ultimo TextBox modificabile per digitare un comando, in entrata gestire il testo inserito rendere il TextBox di sola lettura e aggiungere un nuovo Textbox in fondo –

risposta

28

Dato che si desidera che emuli la console, lo farei in questo modo. Nota che dovresti gestire i comandi e generare da te i risultati.

Page.xaml

<Window x:Class="ConsoleEmulation.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MainWindow" MinHeight="350" MinWidth="525" Height="350" Width="525"> 
    <Grid> 
     <ScrollViewer Name="Scroller" Margin="0" Background="Black"> 
      <StackPanel> 
       <ItemsControl ItemsSource="{Binding ConsoleOutput, Mode=OneWay}"> 
        <ItemsControl.ItemTemplate> 
         <DataTemplate> 
          <TextBlock Text="{Binding Path=.}" Foreground="White" FontFamily="Consolas"/> 
         </DataTemplate> 
        </ItemsControl.ItemTemplate> 
       </ItemsControl> 
       <TextBox Text="{Binding ConsoleInput, Mode=TwoWay}" Background="Black" Foreground="White" FontFamily="Consolas" Name="InputBlock" BorderBrush="{x:Null}" SelectionBrush="{x:Null}" /> 
      </StackPanel> 
     </ScrollViewer> 
    </Grid> 
</Window> 

page.xaml.cs

public partial class MainWindow : Window 
{ 
    ConsoleContent dc = new ConsoleContent(); 

    public MainWindow() 
    { 
     InitializeComponent(); 
     DataContext = dc; 
     Loaded += MainWindow_Loaded; 
    } 

    void MainWindow_Loaded(object sender, RoutedEventArgs e) 
    { 
     InputBlock.KeyDown += InputBlock_KeyDown; 
     InputBlock.Focus(); 
    } 

    void InputBlock_KeyDown(object sender, KeyEventArgs e) 
    { 
     if (e.Key == Key.Enter) 
     { 
      dc.ConsoleInput = InputBlock.Text; 
      dc.RunCommand(); 
      InputBlock.Focus(); 
      Scroller.ScrollToBottom(); 
     } 
    } 
} 

public class ConsoleContent : INotifyPropertyChanged 
{ 
    string consoleInput = string.Empty; 
    ObservableCollection<string> consoleOutput = new ObservableCollection<string>() { "Console Emulation Sample..." }; 

    public string ConsoleInput 
    { 
     get 
     { 
      return consoleInput; 
     } 
     set 
     { 
      consoleInput = value; 
      OnPropertyChanged("ConsoleInput"); 
     } 
    } 

    public ObservableCollection<string> ConsoleOutput 
    { 
     get 
     { 
      return consoleOutput; 
     } 
     set 
     { 
      consoleOutput = value; 
      OnPropertyChanged("ConsoleOutput"); 
     } 
    } 

    public void RunCommand() 
    { 
     ConsoleOutput.Add(ConsoleInput); 
     // do your stuff here. 
     ConsoleInput = String.Empty; 
    } 


    public event PropertyChangedEventHandler PropertyChanged; 
    void OnPropertyChanged(string propertyName) 
    { 
     if (null != PropertyChanged) 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 
+0

Questo piuttosto inchiodato! Eccellente! Questa è la roba che ho sprecato per ore e ho fallito terribilmente :-) Grazie mille! – FrankyTheDumb

+0

Non riesco a far funzionare questa risposta in ms visual studio e apprezzerei le istruzioni di costruzione/progetto o, se necessario, eventuali correzioni. – user3461121

3

Sapevate che è possibile visualizzare una finestra della console dall'applicazione utilizzando AllocConsole?

Questo è un modo semplice per creare un'applicazione "dual-mode" può essere una console di o un'applicazione di moduli di Windows.

[DllImport("kernel32")] 
static extern bool AllocConsole(); 

Oppure si può usare questo:

<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition/> 
     <RowDefinition Height="30"/> 
    </Grid.RowDefinitions> 
    <TextBlock Text="Console contents..." HorizontalAlignment="Stretch" VerticalAlignment="Stretch" x:Name="ConsoleTextBlock"/> 
    <DockPanel Grid.Row="1"> 
     <TextBox/> 
    </DockPanel> 
</Grid> 

Per un aspetto migliore, sostituire il TextBlock con un ListBox e stile ItemTemplate di conseguenza.

+1

Anche se questo è abbastanza carino e semplice, non è proprio quello che stavo cercando. Mi piacerebbe o mettere una console in una finestra wpf (non in esecuzione separatamente) O emulare la console stessa. Ma grazie mille comunque! – FrankyTheDumb

+2

Quindi, ti suggerisco di dare un'occhiata a questo: http://www.codeproject.com/Articles/247280/WPF-Command-Prompt – animaonline

+0

Che lo ha inchiodato troppo, grazie per il link! – FrankyTheDumb

0

non l'ho fatto io, ma è uno dei miei "Lo farò se ho tempo "-Progetti. Così Sto ancora cercando di un'implementazione esistente :-P

In ogni modo alcune riflessioni:

L'applroach utilizzare Visuals (vale a dire Ellissi, TextBlocks) non è probabilmente una buona idea. Pensa a cosa deve succedere se vuoi 200x100 caratteri. Forse anche un backbuffer. Tenendolo tutto in memoria + disegnandolo .... sarà incredibilmente lento.

Quindi l'approccio migliore (o addirittura giusto) è "disegnare te stesso". Poiché WPF è backbuffato e non si desidera visualizzare una bitmap arbitraria, l'approccio più probabile sarebbe quello di creare un nuovo UserControl e sovrascrivere il suo Paint-Method. Si preferisce derivare da Control, ma UserControl può avere contenuto, quindi è possibile mostrare qualcosa come l'icona di un indicatore di connessione all'interno.

Per quanto riguarda l'architettura, suggerirei di creare una proprietà di dipendenza Buffer (ConsoleBuffer) che contiene il modello di buffer della console. Un altro DP terrebbe la posizione in alto a sinistra Posizione (long).Determina dove avviare il display (mentre si guarda indietro). Il modello di console vorrei creare una classe che contenga un char[] e un Color[] (unidimensionale). Utilizzare la suddivisione in linea e i caratteri \n per creare linee (perché questo è il carattere di una console). Quindi, se ridimensionate il controllo, il flusso riprenderà senza che il buffer debba essere riassegnato. Puoi lavorare con ** ConsoleBuffer ** di dimensioni diverse (per un diverso numero di look dietro i caratteri).

ConsoleBuffer.Write(string s) è il tuo metodo per fare cose.

Forse è consigliabile tenere array di array char[][] per rappresentare le linee .... ma questo è fino a scoprirlo durante la programmazione.

-3

Secondo la mia comprensione della tua domanda, stai cercando una console nella tua applicazione wpf.

Per far questo vai alle proprietà e sotto applicazione modificare il tipo di output di Applicazione console.

Ora si può facilmente utilizzare la console come

//Input 
    string Input=Console.ReadLine(); 

//Output 
    Console.Write("something"); 
+0

Penso che tu abbia perso il punto. Sta chiedendo di avere una console all'interno della sua applicazione, non come "convertire" la sua applicazione in console – SOReader