亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

WPF 中的數獨 - 我應該為表格使用什么基本元素?

WPF 中的數獨 - 我應該為表格使用什么基本元素?

C#
慕的地6264312 2022-07-10 10:27:39
我用 C#、XAML 和 MVVM-Light構建了一個非?;镜臄氮殤贸绦?。MainWindow 有一個 9x9 的網格和每個單元格的 81 個文本框,而 MainViewModel 有 81 個 int 屬性。不漂亮。數獨表看起來不像經典的表,沒有“更粗的邊框”來區分每個象限?,F在,我想更上一層樓,讓它變得漂亮實用。每個單元格內容都必須是“響應式”的?即根據窗口的寬度/高度調整大小(字體大?。N乙呀涢_始研究處理字體顏色、背景顏色等的 CellUserControl。主窗口的基礎應該是什么?網格、表格、列表框、自定義?我嘗試了 Grid 和 Table,但通常最終會遇到死胡同。XAML 變得非常冗長和重復。我記得 MS 展示了 WPF 的強大功能,ListBox 顯示為輪播,只需應用樣式即可。這是一條有效的路徑嗎?自定義控件:它是矯枉過正還是完全適合這種情況?順便說一句,我將大量使用 MVVM-Light 和數據綁定。
查看完整描述

3 回答

?
拉風的咖菲貓

TA貢獻1995條經驗 獲得超2個贊

由于所有單元格都應具有相同的大小,因此您也可以使用UniformGrid。正如 Leo Bartkus 建議的那樣,您可以使用代碼隱藏來生成單元格和文本框。為此,首先在 XAML 中為數獨表創建一個占位符:


<!-- Placeholder for Sudoku table (filled in code-behind) -->

<Border x:Name="SudokuTable" />

假設您使用的是Window,這是代碼隱藏:


public partial class MainWindow : Window

{

    private const int InnerWidth = 3;

    private const int OuterWidth = InnerWidth * InnerWidth;


    private const int Thin = 1;

    private const int Thick = 3;


    public MainWindow()

    {

        InitializeComponent();

        InitializeViewModel();

        InitializeSudokuTable();

    }


    public SudokuViewModel ViewModel => (SudokuViewModel)DataContext;


    private void InitializeViewModel()

    {

        DataContext = new SudokuViewModel(OuterWidth);

    }


    private void InitializeSudokuTable()

    {

        var grid = new UniformGrid

        {

            Rows = OuterWidth,

            Columns = OuterWidth

        };


        for (var i = 0; i < OuterWidth; i++)

        {

            for (var j = 0; j < OuterWidth; j++)

            {

                var border = CreateBorder(i, j);

                border.Child = CreateTextBox(i, j);

                grid.Children.Add(border);

            }

        }


        SudokuTable.Child = grid;

    }


    private static Border CreateBorder(int i, int j)

    {

        var left = j % InnerWidth == 0 ? Thick : Thin;

        var top = i % InnerWidth == 0 ? Thick : Thin;

        var right = j == OuterWidth - 1 ? Thick : 0;

        var bottom = i == OuterWidth - 1 ? Thick : 0;


        return new Border

        {

            BorderThickness = new Thickness(left, top, right, bottom),

            BorderBrush = Brushes.Black

        };

    }


    private TextBox CreateTextBox(int i, int j)

    {

        var textBox = new TextBox

        {

            VerticalAlignment = VerticalAlignment.Center,

            HorizontalAlignment = HorizontalAlignment.Center

        };


        var binding = new Binding

        {

            Source = ViewModel,

            Path = new PropertyPath($"[{i},{j}]"),

            Mode = BindingMode.TwoWay

        };


        textBox.SetBinding(TextBox.TextProperty, binding);


        return textBox;

    }

}

嵌套循環為 81 個單元創建每個Border和TextBox。邊框的粗細是根據當前單元格的位置確定的。這將為您提供典型的數獨表外觀。


文本框數據綁定到視圖模型的二維索引器屬性。這是視圖模型:


public class SudokuViewModel : ViewModelBase

{

    private readonly string[,] _values;


    public SudokuViewModel(int width)

    {

        _values = new string[width, width];

    }


    public string this[int i, int j]

    {

        get => _values[i, j];

        set => Set(ref _values[i, j], value);

    }

}

此索引器返回一個字符串,但您可能希望將其更改為整數并進行適當的轉換和錯誤檢查。PropertyChanged在任何情況下,它都使用 MVVM Light在索引器屬性更新時引發事件。


我在這里用我的解決方案創建了一個存儲庫:https ://github.com/redcurry/Sudoku 。


查看完整回答
反對 回復 2022-07-10
?
LEATH

TA貢獻1936條經驗 獲得超7個贊

每個人的答案都很好,你的想法讓我專注于一個目標:)


到目前為止,這就是我所在的位置。


XAML:我正在使用詳細的 XAML 方法和網格。


網格:11x11 -(數獨單元格為 9x9 + 邊框為 2x2)。


<Grid Grid.Row="1" >

        <Grid.ColumnDefinitions>

            <ColumnDefinition/>

            <ColumnDefinition/>

            <ColumnDefinition/>


            <ColumnDefinition Width="2px"/>


            <ColumnDefinition/>

            <ColumnDefinition/>

            <ColumnDefinition/>


            <ColumnDefinition Width="2px"/>


            <ColumnDefinition/>

            <ColumnDefinition/>

            <ColumnDefinition/>

        </Grid.ColumnDefinitions>


        <Grid.RowDefinitions>

            <RowDefinition/>

            <RowDefinition/>

            <RowDefinition/>


            <RowDefinition Height="2px"/>


            <RowDefinition/>

            <RowDefinition/>

            <RowDefinition/>


            <RowDefinition Height="2px"/>


            <RowDefinition/>

            <RowDefinition/>

            <RowDefinition/>

        </Grid.RowDefinitions>


        <Rectangle Grid.Row="0" Grid.Column="3" Grid.RowSpan="11" Fill="Black"></Rectangle>

        <Rectangle Grid.Row="0" Grid.Column="7" Grid.RowSpan="11" Fill="Black"></Rectangle>

        <Rectangle Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="11" Fill="Black"></Rectangle>

        <Rectangle Grid.Row="7" Grid.Column="0" Grid.ColumnSpan="11" Fill="Black"></Rectangle>


        <local:CellUserControl Grid.Row="0" Grid.Column="0"  DataContext="{Binding Path=Cells[0], Source={StaticResource Locator}}"/>

        <local:CellUserControl Grid.Row="0" Grid.Column="1"  DataContext="{Binding Path=Cells[1], Source={StaticResource Locator}}"/>

...

我很懶,所以我最終使用 Excel 電子表格來枚舉 81 個單元格,并使用 Floor.Math、MOD 和 Concatenate 的組合 :)


下一個挑戰是將 81 MVVM 屬性重構為更微不足道的東西。在 XAML 中:語法為 {Binding Path=Cells[0]} 并選擇(暫時)將屬性放在 ViewModelLocator 中。


    public IList<CellViewModel> Cells

    {

        get

        {

            return new List<CellViewModel>(ServiceLocator.Current.GetAllInstances<CellViewModel>());

        }

    }

XAML 和代碼是干凈的。我喜歡它,到目前為止。我仍在處理 IList 的正確位置 - 它應該保留在 ViewModelLocator 中還是應該實際上在 MainViewModel 中?我想,要回答這個問題,我必須做一些單元測試。


查看完整回答
反對 回復 2022-07-10
?
MMMHUHU

TA貢獻1834條經驗 獲得超8個贊

這是我如何用網格做數獨的一個例子......


<Grid>



 <Grid.RowDefinitions>

        <RowDefinition Height="*"/>

        <RowDefinition Height="*"/>

        <RowDefinition Height="*"/>

        <RowDefinition Height="5"/>

        <RowDefinition Height="*"/>

        <RowDefinition Height="*"/>

        <RowDefinition Height="*"/>

        <RowDefinition Height="5"/>

        <RowDefinition Height="*"/>

        <RowDefinition Height="*"/>

        <RowDefinition Height="*"/>

    </Grid.RowDefinitions>

    <Grid.ColumnDefinitions>

        <ColumnDefinition Width="*"/>

        <ColumnDefinition Width="*"/>

        <ColumnDefinition Width="*"/>

        <ColumnDefinition Width="5"/>

        <ColumnDefinition Width="*"/>

        <ColumnDefinition Width="*"/>

        <ColumnDefinition Width="*"/>

        <ColumnDefinition Width="5"/>

        <ColumnDefinition Width="*"/>

        <ColumnDefinition Width="*"/>

        <ColumnDefinition Width="*"/>

    </Grid.ColumnDefinitions>

    <TextBox x:Name="textBox00" TextWrapping="Wrap" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Text="1"/>

    <TextBox x:Name="textBox00_Copy" TextWrapping="Wrap" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Text="1" Grid.Column="1"/>

    <TextBox x:Name="textBox00_Copy1" TextWrapping="Wrap" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Text="1"  Grid.Column="2"/>

    <TextBox x:Name="textBox00_Copy2" TextWrapping="Wrap" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Text="1"  Grid.Column="4"/>

    <TextBox x:Name="textBox00_Copy3" TextWrapping="Wrap" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Text="1"  Grid.Column="5"/>

    <TextBox x:Name="textBox00_Copy4" TextWrapping="Wrap" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Text="1" Grid.Column="6"/>

    <TextBox x:Name="textBox00_Copy5" TextWrapping="Wrap" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Text="1"  Grid.Column="2" Grid.Row="1"/>

    <TextBox x:Name="textBox00_Copy6" TextWrapping="Wrap" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Text="1" Grid.Column="4" Grid.Row="1"/>

    <TextBox x:Name="textBox00_Copy7" TextWrapping="Wrap" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Text="1" Grid.Column="5" Grid.Row="1"/>

    <TextBox x:Name="textBox00_Copy8" TextWrapping="Wrap" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Text="1"  Grid.Column="1" Grid.Row="1"/>

    <TextBox x:Name="textBox00_Copy9" TextWrapping="Wrap" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Text="1"  Grid.Column="1" Grid.Row="2"/>

    <TextBox x:Name="textBox00_Copy10" TextWrapping="Wrap" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Text="1"  Grid.Column="2" Grid.Row="2"/>

    <TextBox x:Name="textBox00_Copy11" TextWrapping="Wrap" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Text="1"  Grid.Column="4" Grid.Row="2"/>

    <Rectangle Grid.Column="3" Fill="#FF663003" Grid.RowSpan="12"/>

    <Rectangle Grid.Column="7" Fill="#FF663003" Grid.RowSpan="12"/>

    <Rectangle Grid.Row="3" Fill="#FF663003" Grid.ColumnSpan="12"/>

    <Rectangle Grid.Row="7" Fill="#FF663003" Grid.ColumnSpan="12"/>

這只是默認的文本框樣式。您可以使用用戶控件使其不同,或者您可以通過在 Blend for Visual Studio 中加載 xaml 來為文本框制作自定義樣式,右鍵單擊文本框并選擇編輯模板.. -> 編輯副本


查看完整回答
反對 回復 2022-07-10
  • 3 回答
  • 0 關注
  • 154 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號