You know that moment when you read a customer review and think, “Wow, this sounds positive… I think?”—only to realize they were actually being sarcastic? Yeah, that’s the kind of ambiguity that got me obsessed with sentiment analysis.

I hit this wall while building a customer feedback dashboard for a .NET-based product. The client wanted something smarter than just counting keywords like “great” or “bad.” They needed something that could understand tone. But here’s the catch—they didn’t want to send data to the cloud, pay for another API, or rewrite the whole thing in Python. Just good ol’ C#.

That’s when I had the “aha!” moment: ML.NET.

If you’ve ever wondered what sentiment analysis is and whether you can run it locally in your C# app without spinning up Azure or TensorFlow pipelines, the answer is yes. And it’s surprisingly approachable. ML.NET lets you train, evaluate, and use machine learning models right inside your .NET project. No switching stacks, no black-box APIs, no monthly bills that sneak up on you.

So why use ML.NET for sentiment analysis? Because it fits seamlessly into our existing .NET workflow – whether you’re building a WPF desktop app, a Blazor server app, or even a CLI tool. And more importantly, it gives you full control over your model, your data, and your logic.

In this post, I’ll walk you through how I built a real sentiment classifier in C#—trained on sample data, saved to disk, and fully integrated with a simple WPF GUI for easy testing. This is for devs like us who want to build machine learning in C# locally and have something tangible to show for it.

Whether you’re working on customer feedback tools, support ticket triaging, or social media monitoring, this approach gives you a powerful and private way to detect sentiment—without leaving the .NET ecosystem.

Let’s get into it.


Table of Contents

Prerequisites

🧠 Knowledge & Experience

  • Intermediate C# skills
    You should be comfortable with classes, async/await, and basic project structure. If you’ve built a few apps or APIs, you’re ready.
  • Familiarity with Visual Studio (or JetBrains Rider)
    We’ll be working inside an IDE that supports .NET 8 development. Visual Studio 2022 or newer is perfect.
  • Basic understanding of machine learning concepts
    No deep learning PhD required—just know what a “model”, “training data”, and “prediction” mean. We’ll keep the ML.NET side approachable.

🛠 Tools & Frameworks

  • .NET 8 SDK
    Required to build and run the app. Download it from the official .NET site if you haven’t already.
  • ML.NET NuGet packages
    Specifically:
    • Microsoft.ML
    • Microsoft.ML.Data
      We’ll install these into the project to handle training and prediction.
  • WPF or WinForms knowledge (optional)
    We’re using WPF for the GUI, but you can swap in whatever UI tech you prefer. Knowing XAML helps, but even if you’re new to it, the snippets will be easy to follow.
  • CSV editor or spreadsheet app (optional)
    If you want to tweak the training data, it’s helpful to view or edit CSV files with Excel, LibreOffice, or VS Code.

✅ If You’ve Got Most of These, You’re Good

You don’t need to be a machine learning expert or a XAML wizard. As long as you’re comfortable in C# and Visual Studio, you’ll be able to follow along, learn something useful, and walk away with a working ML.NET sentiment model—plus a GUI to show it off.


Project Setup: Getting Your ML.NET + GUI Project Ready

Let’s set up the environment together—no surprises, no weird errors at runtime. We’re going to build a WPF desktop app that uses ML.NET for sentiment analysis, trained and executed locally. If you’ve got Visual Studio and .NET 8 installed, you’re already halfway there.

🧰 Step 1: Create the Solution

Open Visual Studio and create a new WPF App project:

  1. File > New > Project
  2. Search for “WPF App (.NET Core)”
  3. Name it something like SentimentAnalyzerApp
  4. Select .NET 8 as the target framework

📦 Step 2: Install ML.NET NuGet Packages

We’ll need a few ML.NET packages for training and prediction. Open the NuGet Package Manager or use the CLI:

dotnet add package Microsoft.ML
dotnet add package Microsoft.ML.Data

If you’re planning to use Model Builder, you can also install:

dotnet tool install -g mlnet

🗃 Step 3: Add a Sample CSV Dataset

Create a Data folder in your project and drop in a CSV file like this:

Sentiment,Text
1,This product is amazing!
0,It was a total waste of money.

Name it sentiment_data.csv. This will be our training data.

🔍 Tip: Make sure your CSV uses comma delimiters and UTF-8 encoding. ML.NET is picky about clean headers.


🧠 Step 4: Check That Everything Builds

Run a quick build:

dotnet build

If you get a TargetFramework error, double-check you picked .NET 8 when creating the project. You can fix it manually in the .csproj:

<TargetFramework>net8.0-windows</TargetFramework>

⚠️ Gotcha: For WPF to work with .NET 8, make sure -windows is part of the framework string. Without it, WPF features won’t work properly.

✅ You’re Set

At this point, you’ve:

  • Installed ML.NET
  • Created a WPF .NET 8 app
  • Loaded sample data
  • Confirmed the build runs clean

We’re now ready to write the sentiment analysis logic and train the model. Let’s go.


Part 1: Training the Sentiment Model with ML.NET

Alright, time to get to the fun part—training the model. This is where ML.NET shines for C# devs: no Python, no cloud, just clean code and local files. We’re going to build a simple binary sentiment classifier that labels text as either positive (1) or negative (0), using a small CSV dataset.

Here’s what we’ll do step-by-step:

  • Load training data from a CSV file
  • Define a strongly-typed schema
  • Build an ML pipeline (data preprocessing + trainer)
  • Train the model and evaluate accuracy
  • Save the model for later use in our GUI

🗃 Step 1: Prepare the CSV Dataset

Make sure your CSV looks like this:

Sentiment,Text
1,I love this product!
0,This is the worst thing I've bought.
1,Absolutely fantastic service.
0,I will never use this again.

Name it sentiment_data.csv and put it in a Data folder within your project.

🧾 Step 2: Define the Data Schema

In ML.NET, we use POCO classes to describe the structure of input and output data. Here’s what that looks like:

public class SentimentData
{
    [LoadColumn(0)]
    public bool Sentiment;

    [LoadColumn(1)]
    public string Text;
}

public class SentimentPrediction
{
    [ColumnName("PredictedLabel")]
    public bool Sentiment;

    public float Probability;
    public float Score;
}

We’re telling ML.NET:

  • The first column is the label (1 = positive, 0 = negative)
  • The second column is the text we want to analyze

🔧 Step 3: Build the ML Pipeline

Here’s where we define how the data flows through transformations and into a binary classifier:

var mlContext = new MLContext();

var dataPath = Path.Combine(Environment.CurrentDirectory, "Data", "sentiment_data.csv");
var dataView = mlContext.Data.LoadFromTextFile<SentimentData>(
    path: dataPath,
    hasHeader: true,
    separatorChar: ',');

// Define pipeline
var pipeline = mlContext.Transforms.Text.FeaturizeText(
        outputColumnName: "Features",
        inputColumnName: nameof(SentimentData.Text))
    .Append(mlContext.BinaryClassification.Trainers.SdcaLogisticRegression(
        labelColumnName: nameof(SentimentData.Sentiment),
        featureColumnName: "Features"));

What’s happening here?

  • FeaturizeText converts raw text into a numeric vector (TF-IDF under the hood)
  • SdcaLogisticRegression is a solid starting point for binary classification
  • We bind the label and features based on our SentimentData model

🧠 Step 4: Train and Evaluate the Model

Now, let’s train the model and test it against the same data (for simplicity—for real projects, split your dataset).

var model = pipeline.Fit(dataView);

// Evaluate accuracy
var predictions = model.Transform(dataView);
var metrics = mlContext.BinaryClassification.Evaluate(predictions);

Console.WriteLine($"Accuracy: {metrics.Accuracy:P2}");
Console.WriteLine($"AUC: {metrics.AreaUnderRocCurve:P2}");

For small test projects, evaluating on the same data is fine. For production models, always use a train/test split to avoid overfitting.

💾 Step 5: Save the Model to Disk

You’ll want to reuse this model in your GUI later, so let’s persist it:

var modelPath = Path.Combine(Environment.CurrentDirectory, "Data", "SentimentModel.zip");
mlContext.Model.Save(model, dataView.Schema, modelPath);

This .zip file contains everything: schema, preprocessing pipeline, and trained weights.

Done. You’ve just trained your first ML.NET sentiment model.
It’s local, it’s fast, and it’s yours. Up next: let’s load this model into a GUI and put it to use.


Part 2: Loading and Using the Model in Your App

Now that we’ve trained and saved our sentiment model, let’s bring it to life inside your .NET app. This part is all about prediction—taking user input and getting back a confidence score and sentiment label. It’s where your machine learning work starts feeling real.

We’ll:

  • Load the model from disk
  • Create a lightweight prediction engine
  • Pass in sample text
  • (Optionally) show the probability for some extra insight

This works great whether you’re wiring it into a WPF GUI or calling it from a console app or API.

📦 Step 1: Load the Trained ML.NET Model

The model we saved in Part 1 as SentimentModel.zip needs to be loaded before we can make predictions.

var mlContext = new MLContext();

var modelPath = Path.Combine(Environment.CurrentDirectory, "Data", "SentimentModel.zip");
ITransformer loadedModel = mlContext.Model.Load(modelPath, out var inputSchema);

ML.NET loads both the model pipeline and the data schema used during training. This ensures predictions match the expected input format.

🔮 Step 2: Create the Prediction Engine

The PredictionEngine is a simple helper for doing one-off predictions. It’s lightweight, but not thread-safe, so don’t use it in multi-threaded production scenarios (for that, use PredictionEnginePool).

var predictionEngine = mlContext.Model.CreatePredictionEngine<SentimentData, SentimentPrediction>(loadedModel);

🧪 Step 3: Run a Sentiment Prediction in C#

Now, let’s run a prediction using some sample input. This is the same structure your GUI will eventually call.

var sampleInput = new SentimentData
{
    Text = "I really love how smooth this app feels!"
};

var prediction = predictionEngine.Predict(sampleInput);

Console.WriteLine($"Text: {sampleInput.Text}");
Console.WriteLine($"Predicted Sentiment: {(prediction.Sentiment ? "Positive" : "Negative")}");
Console.WriteLine($"Confidence: {prediction.Probability:P2}");

The Probability score tells you how confident the model is in its classification—useful for borderline texts.

✅ That’s it. With just a few lines, you’re loading and using a machine learning model trained entirely in C#.
No external API calls. No Python bridge. Just native .NET code.

Next up, we’ll wire this into a clean WPF GUI so users can try it out themselves.


Part 3: Adding a GUI – WPF Integration

Console apps are great for testing, but if you’re building tools for end users (or just want something less hacky), a desktop GUI makes everything feel more polished. Let’s wire up a simple WPF interface that lets you input a sentence, click a button, and instantly see whether the model thinks it’s positive or negative.

You’ll get a clean layout, minimal MVVM structure, and instant feedback—all while running your ML.NET model under the hood.

🧱 Step 1: Add a Basic WPF Window

Open your MainWindow.xaml and replace the default markup with a minimal, functional UI:

<Window x:Class="SentimentAnalyzerApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Sentiment Analyzer" Height="200" Width="400">
    <Grid Margin="20">
        <StackPanel>
            <TextBox x:Name="InputTextBox"
                     Height="30"
                     PlaceholderText="Enter your text here..." />
            <Button Content="Analyze"
                    Margin="0,10,0,0"
                    Click="Analyze_Click"/>
            <TextBlock x:Name="ResultText"
                       FontSize="16"
                       FontWeight="Bold"
                       Margin="0,10,0,0"
                       Text="Sentiment: -" />
        </StackPanel>
    </Grid>
</Window>

This gives you:

  • A textbox for user input
  • A button to trigger the prediction
  • A text block to show the result

🔌 Step 2: Wire Up the Code-Behind (Quick and Dirty MVVM)

In MainWindow.xaml.cs, load the model and hook up the button logic:

public partial class MainWindow : Window
{
    private readonly MLContext _mlContext;
    private readonly PredictionEngine<SentimentData, SentimentPrediction> _predictionEngine;

    public MainWindow()
    {
        InitializeComponent();

        _mlContext = new MLContext();
        var modelPath = Path.Combine(Environment.CurrentDirectory, "Data", "SentimentModel.zip");
        var loadedModel = _mlContext.Model.Load(modelPath, out var _);
        _predictionEngine = _mlContext.Model.CreatePredictionEngine<SentimentData, SentimentPrediction>(loadedModel);
    }

    private void Analyze_Click(object sender, RoutedEventArgs e)
    {
        var input = InputTextBox.Text;

        if (!string.IsNullOrWhiteSpace(input))
        {
            var prediction = _predictionEngine.Predict(new SentimentData { Text = input });
            var sentiment = prediction.Sentiment ? "Positive 😊" : "Negative 😠";
            var confidence = prediction.Probability.ToString("P0");

            ResultText.Text = $"Sentiment: {sentiment} (Confidence: {confidence})";
        }
    }
}

You:

  • Load the model once during initialization
  • Handle predictions on button click
  • Update the UI with results

✨ Step 3: Optional Polish

Want to go a little further?

  • Add color to the result (Green for positive, Red for negative)
  • Disable the button if the input is empty
  • Auto-focus the textbox on load

This helps your simple GUI for machine learning results feel more responsive and user-friendly.

✅ At the end of this tutorial, you’ll get the full working class (XAML + code-behind), so don’t worry about copying everything perfectly right now. The goal is to understand how the pieces connect.

Next, we’ll look at how to make this more reusable and integrate it into real-world workflows or apps.


Part 4: Making the UX Feel Smarter

Okay, the core functionality is done—you enter text, click a button, and get a sentiment result. But let’s be honest: right now it feels like a basic demo. If we want this to resemble a real product, the user experience needs to respond more intuitively.

Here’s how we’ll enhance the app:

  • Use color-coded results (green for positive, red for negative)
  • Show the confidence score
  • Add quality-of-life touches like disabling the button on empty input and clearing after prediction

These aren’t just cosmetic. They make your app feel alive—like it understands what’s going on.

🎨 Add Color to the Sentiment Output

Let’s update the result TextBlock so its foreground color changes based on the prediction.

Update this section inside your Analyze_Click method:

if (!string.IsNullOrWhiteSpace(input))
{
    var prediction = _predictionEngine.Predict(new SentimentData { Text = input });

    var sentiment = prediction.Sentiment ? "Positive 😊" : "Negative 😠";
    var confidence = prediction.Probability.ToString("P0");

    ResultText.Text = $"Sentiment: {sentiment} (Confidence: {confidence})";
    ResultText.Foreground = prediction.Sentiment
        ? Brushes.ForestGreen
        : Brushes.IndianRed;
}

This makes the sentiment instantly recognizable—even without reading the text.

✅ Disable Button on Empty Input

Prevent unnecessary predictions by disabling the button unless the textbox has content. In MainWindow.xaml, add a TextChanged handler to the TextBox:

<TextBox x:Name="InputTextBox"
         Height="30"
         TextChanged="InputTextBox_TextChanged"
         PlaceholderText="Enter your text here..." />

And in the code-behind:

private void InputTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
    AnalyzeButton.IsEnabled = !string.IsNullOrWhiteSpace(InputTextBox.Text);
}

Make sure your button in XAML has a name:

<Button x:Name="AnalyzeButton"
        Content="Analyze"
        IsEnabled="False"
        Click="Analyze_Click" />

This keeps the UI from feeling “clickable but unresponsive.”

🧹 Optional: Clear Input After Prediction

Some people prefer auto-clearing the input field after submitting:

InputTextBox.Clear();
InputTextBox.Focus();

Add it at the end of Analyze_Click if that fits your app flow.

✅ At the end of this tutorial, you’ll get the full class with all enhancements. These UI touches may seem small, but they massively improve usability and perception of your machine learning app.

Up next, we’ll look at how this kind of setup can be extended to real-world workflows, support ticketing tools, or product feedback systems.


Integration and Real-World Usage

At this point, you’ve got a fully working sentiment analysis app—with a GUI, a trained ML.NET model, and some polished UX. But let’s zoom out for a second:

How would you actually use this in the real world?

That’s the difference between a cool weekend project and something you can ship, maintain, or scale.

Let’s walk through a few practical examples and show how to integrate sentiment analysis in a .NET app, whether it’s customer-facing, internal, or part of a broader toolset.

📬 Use Case 1: Auto-Flag Negative Reviews

Got a product feedback form on your website or app? Add a simple server-side .NET process that classifies each comment as it comes in.

Here’s a pattern that works:

public void OnFeedbackSubmitted(string userComment)
{
    var input = new SentimentData { Text = userComment };
    var prediction = _predictionEngine.Predict(input);

    if (!prediction.Sentiment) // Negative feedback
    {
        // Auto-create a support ticket, escalate, or send alert
        NotifySupportTeam(userComment);
    }
}

You could run this in an ASP.NET Core API, a Windows Service, or even a background job.

🎧 Use Case 2: Analyze Customer Support Logs

Imagine you’re piping support tickets or chat messages into a database. A batch process could scan these and flag the most frustrated customers automatically.

public IEnumerable<SupportAlert> ScanMessages(IEnumerable<string> messages)
{
    return messages
        .Select(msg => new 
        {
            Text = msg,
            Prediction = _predictionEngine.Predict(new SentimentData { Text = msg })
        })
        .Where(x => !x.Prediction.Sentiment) // Only negative
        .Select(x => new SupportAlert { Message = x.Text });
}

Integrate this into your ticketing system or CRM dashboard. It helps teams act faster and prioritize better.

📊 Use Case 3: Product Dashboard Sentiment Summary

If you’re building an internal tool for product managers, showing live sentiment breakdown from NPS surveys, emails, or reviews can be super helpful.

Visualize data like:

  • Percentage of negative vs. positive comments
  • Daily trends in sentiment
  • Top “flagged” messages

This works especially well when you deploy sentiment analysis locally inside your desktop or web app—no API latency, no vendor lock-in.

🔁 Bonus: Re-Training with New Data

One of the best parts about ML.NET is that you’re in control of the model lifecycle.

If you gather more data over time (e.g., thousands of user comments), you can retrain the model and plug it right back into your app without changing your logic.

Just re-run the training pipeline from Part 1 with the new CSV, save it as SentimentModel.zip, and replace the old model file in your app’s Data/ folder.

The prediction code stays the same—your app doesn’t care how the model was trained, just that the structure matches.

✅ At the end of this tutorial, you’ll get the full class and project code with all integrations ready to tweak.

The real win here isn’t just a working ML.NET sentiment app—it’s that now you own the pipeline, and can apply it to real business workflows anytime you want.


Conclusion and Extensions

You made it—from raw CSV data to a fully working sentiment analysis app in C#, complete with a WPF UI and real-time predictions, all powered by ML.NET. No cloud dependencies. No third-party APIs. Just pure .NET, running locally, under your control.

What you’ve built is lightweight, extendable, and practical. It can slot into real apps, automate feedback workflows, or power internal tools. And because it runs on your terms, you can audit, retrain, and scale it however you like.

But we’re just scratching the surface. Here are a few next steps you might want to explore to take this even further:

🎯 Expand to Multi-Class Classification

Right now, the model only predicts positive or negative. But what if you wanted to detect more nuanced emotions—like joy, anger, sadness, or neutral?

ML.NET supports multi-class text classification, and it’s not much different from what you’ve already built. You’d:

  • Add a new column in your dataset for emotion labels
  • Swap out the binary trainer for a multi-class one (like LbfgsMaximumEntropy)
  • Update your prediction class and result UI

🖥 Try Other Frontends – WinForms, Blazor, or Even Console

You’re using WPF now, but this model is UI-agnostic. You could:

  • Plug it into a Blazor Server or Blazor Hybrid app for web-native feel
  • Embed it into a WinForms tool if you’re in a legacy environment
  • Even trigger predictions via a CLI tool for batch jobs

🧠 Train on Your Own Data

This is where your model goes from “demo” to “useful.” Collect support messages, product reviews, or internal survey responses and retrain the model on your domain-specific language.

When trained on real-world examples, accuracy improves dramatically—and your predictions become far more meaningful to your users.

Final Thoughts

ML.NET proves that machine learning in C# doesn’t have to be intimidating. You now have a solid foundation to build smarter .NET apps—ones that understand tone, context, and customer emotion. Whether you’re building dashboards, automations, or product tools, you’re not just coding anymore—you’re giving your apps a layer of intelligence.

Go build something thoughtful. And if you do—drop a link. I’d love to see it.


Bonus: Common Pitfalls and Pro Tips

Before you start shipping your sentiment analyzer into production—or even showing it off to your team—let’s talk about a few things that can sneak up on you. These are hard-earned lessons from building ML.NET apps that feel great in demos but fall apart under real-world pressure.

Whether it’s data issues, sluggish UIs, or false confidence in your model, here’s how to avoid the most common missteps.

⚠️ Don’t Overfit on Tiny Datasets

It’s tempting to train your model on 10–20 rows and call it “good enough.” But ML.NET is still a real ML framework—it’ll happily memorize your training data and give you 98% accuracy on garbage.

Rule of thumb: Aim for at least a few hundred labeled examples for basic binary classification. If that’s not possible, start with pre-trained data or augment your dataset gradually.

🧼 Always Sanitize Your Input Text

Models are only as smart as the input they receive. Extra whitespace, punctuation, emojis, or HTML tags can all throw off predictions—especially if they weren’t present in the training data.

Add basic preprocessing:

inputText = inputText.Trim().ToLower();

For more advanced cleaning, consider removing stop words or using custom tokenization during the training pipeline.

🕒 UI Freezing? Use Async Prediction

Prediction itself is fast, but doing it on the UI thread in a WPF app can still cause momentary stutters, especially if you add logging or file I/O.

Wrap predictions in a Task.Run call to keep the interface snappy:

private async void Analyze_Click(object sender, RoutedEventArgs e)
{
    AnalyzeButton.IsEnabled = false;
    var input = InputTextBox.Text;

    var prediction = await Task.Run(() => _predictionEngine.Predict(new SentimentData { Text = input }));

    // Update UI here...
    AnalyzeButton.IsEnabled = true;
}

This is a small fix that gives your app a big performance feel.

📈 Monitor Accuracy and Retrain Over Time

Your model isn’t a fire-and-forget tool. Language evolves. User tone shifts. Slang changes.

Set a schedule (monthly or quarterly) to:

  • Review a batch of predictions manually
  • Check for false positives/negatives
  • Retrain the model with fresh, labeled data if accuracy starts to drift

Even if you’re not building a massive product, this makes your app feel alive and always improving.

TL;DR for the Pros:

  • ✅ More data beats fancy tuning
  • ✅ Clean text = better predictions
  • ✅ Keep your UI async and smooth
  • ✅ Don’t trust a model you haven’t revisited in months

These aren’t just “good to know”—they’re the difference between a toy and a tool. You’ve already done the hard part by getting the app working. Now make sure it keeps working well.


🧩 Full Code: Sentiment Analysis App with ML.NET + WPF

Here’s everything we built in this tutorial, all in one place. No guesswork—just clean, functional code you can copy, run, and modify.

📁 Models/SentimentData.cs

Purpose: Defines input and output data structures for ML.NET training and prediction
Related to: Part 1: Training the Sentiment Model

using Microsoft.ML.Data;

namespace SentimentAnalyzerApp.Models
{
    public class SentimentData
    {
        [LoadColumn(0)]
        public bool Sentiment;

        [LoadColumn(1)]
        public string Text;
    }

    public class SentimentPrediction
    {
        [ColumnName("PredictedLabel")]
        public bool Sentiment;

        public float Probability;
        public float Score;
    }
}

📁 Training/ModelTrainer.cs

Purpose: Loads data, builds a pipeline, trains and saves the ML.NET model
Related to: Part 1: Training the Sentiment Model

using Microsoft.ML;
using SentimentAnalyzerApp.Models;

namespace SentimentAnalyzerApp.Training
{
    public class ModelTrainer
    {
        public static void TrainAndSaveModel()
        {
            var mlContext = new MLContext();
            var dataPath = Path.Combine(Environment.CurrentDirectory, "Data", "sentiment_data.csv");

            var dataView = mlContext.Data.LoadFromTextFile<SentimentData>(
                path: dataPath,
                hasHeader: true,
                separatorChar: ',');

            var pipeline = mlContext.Transforms.Text.FeaturizeText(
                    outputColumnName: "Features",
                    inputColumnName: nameof(SentimentData.Text))
                .Append(mlContext.BinaryClassification.Trainers.SdcaLogisticRegression(
                    labelColumnName: nameof(SentimentData.Sentiment),
                    featureColumnName: "Features"));

            var model = pipeline.Fit(dataView);

            var modelPath = Path.Combine(Environment.CurrentDirectory, "Data", "SentimentModel.zip");
            mlContext.Model.Save(model, dataView.Schema, modelPath);
        }
    }
}

📁 MainWindow.xaml

Purpose: WPF UI layout with input, button, and result display
Related to: Part 3: Adding a GUI – WPF Integration

<Window x:Class="SentimentAnalyzerApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Sentiment Analyzer" Height="250" Width="450">
    <Grid Margin="20">
        <StackPanel>
            <TextBox x:Name="InputTextBox"
                     Height="30"
                     TextChanged="InputTextBox_TextChanged"
                     PlaceholderText="Type a sentence..." />
            <Button x:Name="AnalyzeButton"
                    Content="Analyze"
                    IsEnabled="False"
                    Margin="0,10,0,0"
                    Click="Analyze_Click"/>
            <TextBlock x:Name="ResultText"
                       FontSize="16"
                       FontWeight="Bold"
                       Margin="0,10,0,0"
                       Text="Sentiment: -" />
        </StackPanel>
    </Grid>
</Window>

📁 MainWindow.xaml.cs

Purpose: Loads ML.NET model, runs predictions, and updates UI
Related to:

  • Part 2: Loading and Using the Model
  • Part 4: Making the UX Feel Smarter
using Microsoft.ML;
using SentimentAnalyzerApp.Models;
using System;
using System.IO;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace SentimentAnalyzerApp
{
    public partial class MainWindow : Window
    {
        private readonly MLContext _mlContext;
        private readonly PredictionEngine<SentimentData, SentimentPrediction> _predictionEngine;

        public MainWindow()
        {
            InitializeComponent();

            _mlContext = new MLContext();
            var modelPath = Path.Combine(Environment.CurrentDirectory, "Data", "SentimentModel.zip");

            var loadedModel = _mlContext.Model.Load(modelPath, out var _);
            _predictionEngine = _mlContext.Model.CreatePredictionEngine<SentimentData, SentimentPrediction>(loadedModel);
        }

        private async void Analyze_Click(object sender, RoutedEventArgs e)
        {
            AnalyzeButton.IsEnabled = false;
            var input = InputTextBox.Text.Trim();

            if (!string.IsNullOrWhiteSpace(input))
            {
                var prediction = await Task.Run(() =>
                    _predictionEngine.Predict(new SentimentData { Text = input }));

                var sentiment = prediction.Sentiment ? "Positive 😊" : "Negative 😠";
                var confidence = prediction.Probability.ToString("P0");

                ResultText.Text = $"Sentiment: {sentiment} (Confidence: {confidence})";
                ResultText.Foreground = prediction.Sentiment
                    ? Brushes.ForestGreen
                    : Brushes.IndianRed;
            }

            AnalyzeButton.IsEnabled = true;
            InputTextBox.Clear();
            InputTextBox.Focus();
        }

        private void InputTextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            AnalyzeButton.IsEnabled = !string.IsNullOrWhiteSpace(InputTextBox.Text);
        }
    }
}

✅ You’re Ready to Build and Ship

These files together form a complete ML.NET-powered WPF sentiment analysis app. Feel free to fork this as a starter project, build on it, or hook it into a bigger system.

If you extend it—multi-class labels, REST API integration, better UI—let me know. I’d love to see what you build next.

What is ML.NET and how is it used in .NET applications?

A: ML.NET is Microsoft’s open-source machine learning framework that allows .NET developers to build, train, and deploy custom machine learning models in C# or F#. It integrates seamlessly with .NET applications such as desktop apps, web APIs, and background services.

Can I do sentiment analysis in C# without using Python or external APIs?

A: Yes, with ML.NET you can perform sentiment analysis entirely in C# using local models. No Python, no third-party services—everything runs within your .NET environment.

How does ML.NET handle text data like user reviews or comments?

A: ML.NET uses built-in text featurization (like TF-IDF vectorization) to convert raw text into numerical features that can be used for classification or regression tasks.

What kind of dataset is required for training a sentiment model?

A: A basic CSV file with two columns—one for the label (positive/negative) and one for the text—is enough. More data helps improve accuracy, but even a few hundred rows can get you started.

Can I use ML.NET models in a WPF or WinForms application?

A: Absolutely. ML.NET models can be loaded and used in any .NET-based desktop application, including WPF, WinForms, and even MAUI or Blazor Hybrid apps.

Is ML.NET suitable for production use?

A: Yes, ML.NET is production-ready and used in many enterprise applications. However, it’s best to monitor accuracy over time and retrain your models periodically with updated data.

How can I improve the accuracy of my ML.NET sentiment model?

A: Use more training data, clean and normalize text input, and consider using domain-specific language samples. You can also experiment with different trainers like FastTree or L-BFGS.

What happens if my input text is empty or malformed?

A: It’s best to sanitize and validate text inputs before sending them to the model. Trim whitespace, remove HTML tags, and handle nulls to prevent unexpected behavior.

Can ML.NET support multi-class sentiment (like anger, joy, neutral)?

A: Yes! ML.NET supports multi-class classification. You just need to update your dataset to include multiple label categories and use a multi-class trainer such as LbfgsMaximumEntropy.

Do I need an internet connection to run sentiment analysis with ML.NET?

A: No internet required. Once the model is trained and saved locally, your app can load and run it entirely offline. This is great for privacy and performance.

How do I retrain an ML.NET model with new data?

A: Just load the new CSV or dataset, run the training pipeline again, and overwrite the existing .zip model file. Your prediction logic can stay the same.

Can I use ML.NET in ASP.NET Core APIs for real-time sentiment analysis?

A: Yes, ML.NET works well in ASP.NET Core applications. For performance, use the PredictionEnginePool to serve predictions safely in concurrent environments.